blob: b3ae050e14e9925129c76ca2e1701e7b614fdcb3 [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;
David du Colombier7af46052012-05-16 14:16:48 +0200531 trashlen = global.tune.bufsize;
532 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200533 }
534 else if (!strcmp(args[0], "tune.maxrewrite")) {
535 if (*(args[1]) == 0) {
536 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
537 err_code |= ERR_ALERT | ERR_FATAL;
538 goto out;
539 }
540 global.tune.maxrewrite = atol(args[1]);
541 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
542 global.tune.maxrewrite = global.tune.bufsize / 2;
543 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100544 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
545 if (global.tune.client_rcvbuf != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
547 err_code |= ERR_ALERT;
548 goto out;
549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
554 }
555 global.tune.client_rcvbuf = atol(args[1]);
556 }
557 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
558 if (global.tune.server_rcvbuf != 0) {
559 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT;
561 goto out;
562 }
563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.server_rcvbuf = atol(args[1]);
569 }
570 else if (!strcmp(args[0], "tune.sndbuf.client")) {
571 if (global.tune.client_sndbuf != 0) {
572 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT;
574 goto out;
575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.tune.client_sndbuf = atol(args[1]);
582 }
583 else if (!strcmp(args[0], "tune.sndbuf.server")) {
584 if (global.tune.server_sndbuf != 0) {
585 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT;
587 goto out;
588 }
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.server_sndbuf = atol(args[1]);
595 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200596 else if (!strcmp(args[0], "tune.pipesize")) {
597 if (*(args[1]) == 0) {
598 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.tune.pipesize = atol(args[1]);
603 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200604 else if (!strcmp(args[0], "tune.http.maxhdr")) {
605 if (*(args[1]) == 0) {
606 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
609 }
610 global.tune.max_http_hdr = atol(args[1]);
611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 else if (!strcmp(args[0], "uid")) {
613 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200614 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 global.uid = atol(args[1]);
624 }
625 else if (!strcmp(args[0], "gid")) {
626 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200627 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT;
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 }
636 global.gid = atol(args[1]);
637 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200638 /* user/group name handling */
639 else if (!strcmp(args[0], "user")) {
640 struct passwd *ha_user;
641 if (global.uid != 0) {
642 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200643 err_code |= ERR_ALERT;
644 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200645 }
646 errno = 0;
647 ha_user = getpwnam(args[1]);
648 if (ha_user != NULL) {
649 global.uid = (int)ha_user->pw_uid;
650 }
651 else {
652 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 +0200653 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200654 }
655 }
656 else if (!strcmp(args[0], "group")) {
657 struct group *ha_group;
658 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200659 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
661 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200662 }
663 errno = 0;
664 ha_group = getgrnam(args[1]);
665 if (ha_group != NULL) {
666 global.gid = (int)ha_group->gr_gid;
667 }
668 else {
669 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 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200671 }
672 }
673 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 else if (!strcmp(args[0], "nbproc")) {
675 if (global.nbproc != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
685 global.nbproc = atol(args[1]);
686 }
687 else if (!strcmp(args[0], "maxconn")) {
688 if (global.maxconn != 0) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697 }
698 global.maxconn = atol(args[1]);
699#ifdef SYSTEM_MAXCONN
700 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
701 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);
702 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200703 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704 }
705#endif /* SYSTEM_MAXCONN */
706 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200707 else if (!strcmp(args[0], "maxconnrate")) {
708 if (global.cps_lim != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT;
711 goto out;
712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718 global.cps_lim = atol(args[1]);
719 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100720 else if (!strcmp(args[0], "maxpipes")) {
721 if (global.maxpipes != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT;
724 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100730 }
731 global.maxpipes = atol(args[1]);
732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 else if (!strcmp(args[0], "ulimit-n")) {
734 if (global.rlimit_nofile != 0) {
735 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT;
737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200743 }
744 global.rlimit_nofile = atol(args[1]);
745 }
746 else if (!strcmp(args[0], "chroot")) {
747 if (global.chroot != NULL) {
748 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200749 err_code |= ERR_ALERT;
750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 }
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 }
757 global.chroot = strdup(args[1]);
758 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200759 else if (!strcmp(args[0], "description")) {
760 int i, len=0;
761 char *d;
762
763 if (!*args[1]) {
764 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
765 file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769
770 for(i=1; *args[i]; i++)
771 len += strlen(args[i])+1;
772
773 if (global.desc)
774 free(global.desc);
775
776 global.desc = d = (char *)calloc(1, len);
777
778 d += sprintf(d, "%s", args[1]);
779 for(i=2; *args[i]; i++)
780 d += sprintf(d, " %s", args[i]);
781 }
782 else if (!strcmp(args[0], "node")) {
783 int i;
784 char c;
785
786 for (i=0; args[1][i]; i++) {
787 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100788 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
789 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200790 break;
791 }
792
793 if (!i || args[1][i]) {
794 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
795 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
796 file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800
801 if (global.node)
802 free(global.node);
803
804 global.node = strdup(args[1]);
805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 else if (!strcmp(args[0], "pidfile")) {
807 if (global.pidfile != NULL) {
808 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT;
810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 }
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200816 }
817 global.pidfile = strdup(args[1]);
818 }
Emeric Bruned760922010-10-22 17:59:25 +0200819 else if (!strcmp(args[0], "unix-bind")) {
820 int cur_arg = 1;
821 while (*(args[cur_arg])) {
822 if (!strcmp(args[cur_arg], "prefix")) {
823 if (global.unix_bind.prefix != NULL) {
824 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
825 err_code |= ERR_ALERT;
826 cur_arg += 2;
827 continue;
828 }
829
830 if (*(args[cur_arg+1]) == 0) {
831 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835 global.unix_bind.prefix = strdup(args[cur_arg+1]);
836 cur_arg += 2;
837 continue;
838 }
839
840 if (!strcmp(args[cur_arg], "mode")) {
841
842 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
843 cur_arg += 2;
844 continue;
845 }
846
847 if (!strcmp(args[cur_arg], "uid")) {
848
849 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
850 cur_arg += 2;
851 continue;
852 }
853
854 if (!strcmp(args[cur_arg], "gid")) {
855
856 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
857 cur_arg += 2;
858 continue;
859 }
860
861 if (!strcmp(args[cur_arg], "user")) {
862 struct passwd *user;
863
864 user = getpwnam(args[cur_arg + 1]);
865 if (!user) {
866 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
867 file, linenum, args[0], args[cur_arg + 1 ]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870 }
871
872 global.unix_bind.ux.uid = user->pw_uid;
873 cur_arg += 2;
874 continue;
875 }
876
877 if (!strcmp(args[cur_arg], "group")) {
878 struct group *group;
879
880 group = getgrnam(args[cur_arg + 1]);
881 if (!group) {
882 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
883 file, linenum, args[0], args[cur_arg + 1 ]);
884 err_code |= ERR_ALERT | ERR_FATAL;
885 goto out;
886 }
887
888 global.unix_bind.ux.gid = group->gr_gid;
889 cur_arg += 2;
890 continue;
891 }
892
Willy Tarreaub48f9582011-09-05 01:17:06 +0200893 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200894 file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
898 }
William Lallemand0f99e342011-10-12 17:50:54 +0200899 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
900 /* delete previous herited or defined syslog servers */
901 struct logsrv *back;
902 struct logsrv *tmp;
903
904 if (*(args[1]) != 0) {
905 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909
910 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
911 LIST_DEL(&tmp->list);
912 free(tmp);
913 }
914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200916 struct logsrv *logsrv;
917
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 if (*(args[1]) == 0 || *(args[2]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
William Lallemand0f99e342011-10-12 17:50:54 +0200923
924 logsrv = calloc(1, sizeof(struct logsrv));
925
926 logsrv->facility = get_log_facility(args[2]);
927 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200930 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932
William Lallemand0f99e342011-10-12 17:50:54 +0200933 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200935 logsrv->level = get_log_level(args[3]);
936 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200938 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200939 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 }
941 }
942
William Lallemand0f99e342011-10-12 17:50:54 +0200943 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200944 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->minlvl = get_log_level(args[4]);
946 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200947 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200948 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200949 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200950 }
951 }
952
Robert Tsai81ae1952007-12-05 10:47:29 +0100953 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100954 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100955 if (!sk) {
956 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100957 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100958 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200959 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100960 goto out;
961 }
William Lallemand0f99e342011-10-12 17:50:54 +0200962 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100963 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100964 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100965 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100966 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
967 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200968 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100969 goto out;
970 }
William Lallemand0f99e342011-10-12 17:50:54 +0200971 logsrv->addr = *sk;
972 if (!get_host_port(&logsrv->addr))
973 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975
William Lallemand0f99e342011-10-12 17:50:54 +0200976 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200977 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100978 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
979 char *name;
980 int len;
981
982 if (global.log_send_hostname != NULL) {
983 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
984 err_code |= ERR_ALERT;
985 goto out;
986 }
987
988 if (*(args[1]))
989 name = args[1];
990 else
991 name = hostname;
992
993 len = strlen(name);
994
995 /* We'll add a space after the name to respect the log format */
996 free(global.log_send_hostname);
997 global.log_send_hostname = malloc(len + 2);
998 snprintf(global.log_send_hostname, len + 2, "%s ", name);
999 }
Kevinm48936af2010-12-22 16:08:21 +00001000 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1001 if (*(args[1]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 free(global.log_tag);
1007 global.log_tag = strdup(args[1]);
1008 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001009 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1010 if (global.spread_checks != 0) {
1011 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT;
1013 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001014 }
1015 if (*(args[1]) == 0) {
1016 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001019 }
1020 global.spread_checks = atol(args[1]);
1021 if (global.spread_checks < 0 || global.spread_checks > 50) {
1022 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 }
1026 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001027 struct cfg_kw_list *kwl;
1028 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001029 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001030
1031 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1032 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1033 if (kwl->kw[index].section != CFG_GLOBAL)
1034 continue;
1035 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1036 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001037 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001038 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001039 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001040 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001041 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001043 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001044 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001045 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 err_code |= ERR_WARN;
1047 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001048 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001050 }
1051 }
1052 }
1053
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001055 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001057
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001059 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001060 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061}
1062
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001063void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001065 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 defproxy.mode = PR_MODE_TCP;
1067 defproxy.state = PR_STNEW;
1068 defproxy.maxconn = cfg_maxpconn;
1069 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001070
1071 defproxy.defsrv.inter = DEF_CHKINTR;
1072 defproxy.defsrv.fastinter = 0;
1073 defproxy.defsrv.downinter = 0;
1074 defproxy.defsrv.rise = DEF_RISETIME;
1075 defproxy.defsrv.fall = DEF_FALLTIME;
1076 defproxy.defsrv.check_port = 0;
1077 defproxy.defsrv.maxqueue = 0;
1078 defproxy.defsrv.minconn = 0;
1079 defproxy.defsrv.maxconn = 0;
1080 defproxy.defsrv.slowstart = 0;
1081 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1082 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1083 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084}
1085
Willy Tarreauade5ec42010-01-28 19:33:49 +01001086
1087static int create_cond_regex_rule(const char *file, int line,
1088 struct proxy *px, int dir, int action, int flags,
1089 const char *cmd, const char *reg, const char *repl,
1090 const char **cond_start)
1091{
1092 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001093 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001094 const char *err;
1095 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001096 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001097
1098 if (px == &defproxy) {
1099 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto err;
1102 }
1103
1104 if (*reg == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto err;
1108 }
1109
1110 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1111 err_code |= ERR_WARN;
1112
Willy Tarreau5321c422010-01-28 20:35:13 +01001113 if (cond_start &&
1114 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001115 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1116 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1117 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001118 err_code |= ERR_ALERT | ERR_FATAL;
1119 goto err;
1120 }
1121 }
1122 else if (cond_start && **cond_start) {
1123 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1124 file, line, cmd, *cond_start);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto err;
1127 }
1128
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001129 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001131 else
1132 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001133
Willy Tarreauade5ec42010-01-28 19:33:49 +01001134 preg = calloc(1, sizeof(regex_t));
1135 if (!preg) {
1136 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1137 err_code = ERR_ALERT | ERR_FATAL;
1138 goto err;
1139 }
1140
1141 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1142 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1143 err_code = ERR_ALERT | ERR_FATAL;
1144 goto err;
1145 }
1146
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001147 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001148 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001149 if (repl && err) {
1150 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1151 file, line, cmd, *err);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto err;
1154 }
1155
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001156 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001157 err_code |= ERR_WARN;
1158
Willy Tarreauf4068b62012-05-08 17:37:49 +02001159 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001160 return err_code;
1161 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001162 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001163 free(preg);
1164 return err_code;
1165}
1166
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001168 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001169 * Returns the error code, 0 if OK, or any combination of :
1170 * - ERR_ABORT: must abort ASAP
1171 * - ERR_FATAL: we can continue parsing but not start the service
1172 * - ERR_WARN: a warning has been emitted
1173 * - ERR_ALERT: an alert has been emitted
1174 * Only the two first ones can stop processing, the two others are just
1175 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001176 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001177int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1178{
1179 static struct peers *curpeers = NULL;
1180 struct peer *newpeer = NULL;
1181 const char *err;
1182 int err_code = 0;
1183
1184 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1185
1186 err = invalid_char(args[1]);
1187 if (err) {
1188 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1189 file, linenum, *err, args[0], args[1]);
1190 err_code |= ERR_ALERT | ERR_FATAL;
1191 }
1192
1193 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1194 /*
1195 * If there are two proxies with the same name only following
1196 * combinations are allowed:
1197 */
1198 if (strcmp(curpeers->id, args[1]) == 0) {
1199 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1200 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1201 err_code |= ERR_WARN;
1202 }
1203 }
1204
1205 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1206 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1207 err_code |= ERR_ALERT | ERR_ABORT;
1208 goto out;
1209 }
1210
1211 curpeers->next = peers;
1212 peers = curpeers;
1213 curpeers->conf.file = file;
1214 curpeers->conf.line = linenum;
1215 curpeers->last_change = now.tv_sec;
1216 curpeers->id = strdup(args[1]);
1217 }
1218 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1219 char *rport, *raddr;
1220 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001221 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001222
1223 if (!*args[2]) {
1224 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1225 file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 err = invalid_char(args[1]);
1231 if (err) {
1232 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1233 file, linenum, *err, args[1]);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237
1238 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1240 err_code |= ERR_ALERT | ERR_ABORT;
1241 goto out;
1242 }
1243
1244 /* the peers are linked backwards first */
1245 curpeers->count++;
1246 newpeer->next = curpeers->remote;
1247 curpeers->remote = newpeer;
1248 newpeer->peers = curpeers;
1249 newpeer->conf.file = file;
1250 newpeer->conf.line = linenum;
1251
1252 newpeer->last_change = now.tv_sec;
1253 newpeer->id = strdup(args[1]);
1254
1255 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001256 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001257 if (rport) {
1258 *rport++ = 0;
1259 realport = atol(rport);
1260 }
1261 if (!realport) {
1262 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
1265 }
1266
Willy Tarreaufab5a432011-03-04 15:31:53 +01001267 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001268 free(raddr);
1269 if (!sk) {
1270 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
1273 }
1274 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001275 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02001276 newpeer->sock = &sock_raw;
1277 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001278
1279 if (!sk) {
1280 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1281 file, linenum, newpeer->addr.ss_family, args[2]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001286 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001287
1288 if (strcmp(newpeer->id, localpeer) == 0) {
1289 /* Current is local peer, it define a frontend */
1290 newpeer->local = 1;
1291
1292 if (!curpeers->peers_fe) {
1293 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1294 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1295 err_code |= ERR_ALERT | ERR_ABORT;
1296 goto out;
1297 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001298
Willy Tarreau237250c2011-07-29 01:49:03 +02001299 init_new_proxy(curpeers->peers_fe);
1300 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001301
1302 curpeers->peers_fe->last_change = now.tv_sec;
1303 curpeers->peers_fe->id = strdup(args[1]);
1304 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001305 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001306 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1307 curpeers->peers_fe->timeout.connect = 5000;
1308 curpeers->peers_fe->accept = peer_accept;
1309 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001310 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001311 err_code |= ERR_FATAL;
1312 goto out;
1313 }
1314 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1315 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1316 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1317 curpeers->peers_fe->listen->accept = session_accept;
1318 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1319 curpeers->peers_fe->listen->handler = process_session;
1320 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001321 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1322 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001323 }
1324 }
1325 } /* neither "peer" nor "peers" */
1326 else if (*args[0] != 0) {
1327 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331
1332out:
1333 return err_code;
1334}
1335
1336
Willy Tarreau3842f002009-06-14 11:39:52 +02001337int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338{
1339 static struct proxy *curproxy = NULL;
1340 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001341 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001342 int rc;
1343 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001344 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001345 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001346 struct logsrv *tmplogsrv;
1347 struct logformat_node *tmplf;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001348 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349
Willy Tarreau977b8e42006-12-29 14:19:17 +01001350 if (!strcmp(args[0], "listen"))
1351 rc = PR_CAP_LISTEN;
1352 else if (!strcmp(args[0], "frontend"))
1353 rc = PR_CAP_FE | PR_CAP_RS;
1354 else if (!strcmp(args[0], "backend"))
1355 rc = PR_CAP_BE | PR_CAP_RS;
1356 else if (!strcmp(args[0], "ruleset"))
1357 rc = PR_CAP_RS;
1358 else
1359 rc = PR_CAP_NONE;
1360
1361 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 if (!*args[1]) {
1363 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1364 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001366 err_code |= ERR_ALERT | ERR_ABORT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001369
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001370 err = invalid_char(args[1]);
1371 if (err) {
1372 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1373 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001375 }
1376
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001377 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1378 /*
1379 * If there are two proxies with the same name only following
1380 * combinations are allowed:
1381 *
1382 * listen backend frontend ruleset
1383 * listen - - - -
1384 * backend - - OK -
1385 * frontend - OK - -
1386 * ruleset - - - -
1387 */
1388
1389 if (!strcmp(curproxy->id, args[1]) &&
1390 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1391 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001392 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1393 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1394 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001396 }
1397 }
1398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001401 err_code |= ERR_ALERT | ERR_ABORT;
1402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001404
Willy Tarreau97cb7802010-01-03 20:23:58 +01001405 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 curproxy->next = proxy;
1407 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001408 curproxy->conf.file = file;
1409 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001410 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001412 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413
1414 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001415 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001416 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001417 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001418 err_code |= ERR_FATAL;
1419 goto out;
1420 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001421 new = curproxy->listen;
1422 while (new != last) {
1423 new->conf.file = file;
1424 new->conf.line = linenum;
1425 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001426 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428 }
1429
1430 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001431 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001432 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001433
Willy Tarreaubaaee002006-06-26 02:48:02 +02001434 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001436 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001437 curproxy->no_options = defproxy.no_options;
1438 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001439 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001440 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001441 curproxy->except_net = defproxy.except_net;
1442 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001443 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001444 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001446 if (defproxy.fwdfor_hdr_len) {
1447 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1448 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1449 }
1450
Willy Tarreaub86db342009-11-30 11:50:16 +01001451 if (defproxy.orgto_hdr_len) {
1452 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1453 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1454 }
1455
Mark Lamourinec2247f02012-01-04 13:02:01 -05001456 if (defproxy.server_id_hdr_len) {
1457 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1458 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1459 }
1460
Willy Tarreau977b8e42006-12-29 14:19:17 +01001461 if (curproxy->cap & PR_CAP_FE) {
1462 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001463 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001464 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465
1466 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001467 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1468 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469
1470 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472
Willy Tarreau977b8e42006-12-29 14:19:17 +01001473 if (curproxy->cap & PR_CAP_BE) {
1474 curproxy->fullconn = defproxy.fullconn;
1475 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001477 if (defproxy.check_req) {
1478 curproxy->check_req = calloc(1, defproxy.check_len);
1479 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1480 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001481 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001483 if (defproxy.expect_str) {
1484 curproxy->expect_str = strdup(defproxy.expect_str);
1485 if (defproxy.expect_regex) {
1486 /* note: this regex is known to be valid */
1487 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1488 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1489 }
1490 }
1491
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (defproxy.cookie_name)
1493 curproxy->cookie_name = strdup(defproxy.cookie_name);
1494 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001495 if (defproxy.cookie_domain)
1496 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001497
Willy Tarreau31936852010-10-06 16:59:56 +02001498 if (defproxy.cookie_maxidle)
1499 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1500
1501 if (defproxy.cookie_maxlife)
1502 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1503
Emeric Brun647caf12009-06-30 17:57:00 +02001504 if (defproxy.rdp_cookie_name)
1505 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1506 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1507
Willy Tarreau01732802007-11-01 22:48:15 +01001508 if (defproxy.url_param_name)
1509 curproxy->url_param_name = strdup(defproxy.url_param_name);
1510 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001511
Benoitaffb4812009-03-25 13:02:10 +01001512 if (defproxy.hh_name)
1513 curproxy->hh_name = strdup(defproxy.hh_name);
1514 curproxy->hh_len = defproxy.hh_len;
1515 curproxy->hh_match_domain = defproxy.hh_match_domain;
1516
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001517 if (defproxy.iface_name)
1518 curproxy->iface_name = strdup(defproxy.iface_name);
1519 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001522 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001523 if (defproxy.capture_name)
1524 curproxy->capture_name = strdup(defproxy.capture_name);
1525 curproxy->capture_namelen = defproxy.capture_namelen;
1526 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528
Willy Tarreau977b8e42006-12-29 14:19:17 +01001529 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001530 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001531 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001532 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001533 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001534 curproxy->uri_auth = defproxy.uri_auth;
1535 curproxy->mon_net = defproxy.mon_net;
1536 curproxy->mon_mask = defproxy.mon_mask;
1537 if (defproxy.monitor_uri)
1538 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1539 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001540 if (defproxy.defbe.name)
1541 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001542 }
1543
1544 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001545 curproxy->timeout.connect = defproxy.timeout.connect;
1546 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001547 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001548 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001549 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001550 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001551 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001552 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001553 curproxy->source_addr = defproxy.source_addr;
1554 }
1555
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001557
1558 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001559 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001560 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001561 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001562 LIST_INIT(&node->list);
1563 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1564 }
1565
William Lallemand723b73a2012-02-08 16:37:49 +01001566 /* copy default log_format to curproxy */
1567 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1568 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1569 memcpy(node, tmplf, sizeof(struct logformat_node));
1570 LIST_INIT(&node->list);
1571 LIST_ADDQ(&curproxy->logformat, &node->list);
1572 }
1573
William Lallemanda73203e2012-03-12 12:48:57 +01001574 /* copy default unique_id to curproxy */
1575 list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
1576 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1577 memcpy(node, tmplf, sizeof(struct logformat_node));
1578 LIST_INIT(&node->list);
1579 LIST_ADDQ(&curproxy->format_unique_id, &node->list);
1580 }
1581
1582 /* copy default header unique id */
1583 if (defproxy.header_unique_id)
1584 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1585
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001587 curproxy->conf.used_listener_id = EB_ROOT;
1588 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001589
Willy Tarreau93893792009-07-23 13:19:11 +02001590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 }
1592 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1593 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001594 /* FIXME-20070101: we should do this too at the end of the
1595 * config parsing to free all default values.
1596 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001597 free(defproxy.check_req);
1598 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001599 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001600 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001601 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001602 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001603 free(defproxy.capture_name);
1604 free(defproxy.monitor_uri);
1605 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001606 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001607 free(defproxy.fwdfor_hdr_name);
1608 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001609 free(defproxy.orgto_hdr_name);
1610 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001611 free(defproxy.server_id_hdr_name);
1612 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001613 free(defproxy.expect_str);
1614 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001615
Willy Tarreaua534fea2008-08-03 12:19:50 +02001616 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001617 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001618
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 /* we cannot free uri_auth because it might already be used */
1620 init_default_instance();
1621 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001622 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 }
1625 else if (curproxy == NULL) {
1626 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 }
1630
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631
1632 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001634 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001635 int cur_arg;
1636
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 if (curproxy == &defproxy) {
1638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001639 err_code |= ERR_ALERT | ERR_FATAL;
1640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001642 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001643 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644
Emeric Bruned760922010-10-22 17:59:25 +02001645 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001646 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001651
1652 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001653
1654 /* NOTE: the following line might create several listeners if there
1655 * are comma-separated IPs or port ranges. So all further processing
1656 * will have to be applied to all listeners created after last_listen.
1657 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001658 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
1661 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001662
Willy Tarreau90a570f2009-10-04 20:54:54 +02001663 new_listen = curproxy->listen;
1664 while (new_listen != last_listen) {
1665 new_listen->conf.file = file;
1666 new_listen->conf.line = linenum;
1667 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001668 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001669 }
1670
Emeric Bruned760922010-10-22 17:59:25 +02001671 /* Set default global rights and owner for unix bind */
1672 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1673 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1674 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001675 cur_arg = 2;
1676 while (*(args[cur_arg])) {
1677 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1678#ifdef SO_BINDTODEVICE
1679 struct listener *l;
1680
Emeric Bruned760922010-10-22 17:59:25 +02001681 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1682 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1683 file, linenum, args[0], args[cur_arg]);
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001688 if (!*args[cur_arg + 1]) {
1689 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1690 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001693 }
1694
1695 for (l = curproxy->listen; l != last_listen; l = l->next)
1696 l->interface = strdup(args[cur_arg + 1]);
1697
1698 global.last_checks |= LSTCHK_NETADM;
1699
1700 cur_arg += 2;
1701 continue;
1702#else
1703 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1704 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
1706 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001707#endif
1708 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001709 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1710#ifdef TCP_MAXSEG
1711 struct listener *l;
1712 int mss;
1713
Emeric Bruned760922010-10-22 17:59:25 +02001714 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1715 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1716 file, linenum, args[0], args[cur_arg]);
1717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
1719 }
1720
Willy Tarreaube1b9182009-06-14 18:48:19 +02001721 if (!*args[cur_arg + 1]) {
1722 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1723 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001724 err_code |= ERR_ALERT | ERR_FATAL;
1725 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001726 }
1727
Willy Tarreau48a7e722010-12-24 15:26:39 +01001728 mss = atoi(args[cur_arg + 1]);
1729 if (!mss || abs(mss) > 65535) {
1730 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001731 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001732 err_code |= ERR_ALERT | ERR_FATAL;
1733 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001734 }
1735
1736 for (l = curproxy->listen; l != last_listen; l = l->next)
1737 l->maxseg = mss;
1738
1739 cur_arg += 2;
1740 continue;
1741#else
1742 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1743 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001746#endif
1747 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001748
1749 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1750#ifdef TCP_DEFER_ACCEPT
1751 struct listener *l;
1752
1753 for (l = curproxy->listen; l != last_listen; l = l->next)
1754 l->options |= LI_O_DEF_ACCEPT;
1755
1756 cur_arg ++;
1757 continue;
1758#else
1759 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1760 file, linenum, args[0], args[cur_arg]);
1761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
1763#endif
1764 }
1765
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001766 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001767#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001768 struct listener *l;
1769
Emeric Bruned760922010-10-22 17:59:25 +02001770 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1771 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1772 file, linenum, args[0], args[cur_arg]);
1773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
1775 }
1776
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001777 for (l = curproxy->listen; l != last_listen; l = l->next)
1778 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001779
1780 cur_arg ++;
1781 continue;
1782#else
1783 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1784 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001787#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001788 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001789
Willy Tarreau8a956912010-10-15 14:27:08 +02001790 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1791 struct listener *l;
1792
1793 for (l = curproxy->listen; l != last_listen; l = l->next)
1794 l->options |= LI_O_ACC_PROXY;
1795
1796 cur_arg ++;
1797 continue;
1798 }
1799
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001800 if (!strcmp(args[cur_arg], "name")) {
1801 struct listener *l;
1802
1803 for (l = curproxy->listen; l != last_listen; l = l->next)
1804 l->name = strdup(args[cur_arg + 1]);
1805
1806 cur_arg += 2;
1807 continue;
1808 }
1809
1810 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001811 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001812 struct listener *l;
1813
1814 if (curproxy->listen->next != last_listen) {
1815 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1816 file, linenum, args[cur_arg]);
1817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
1819 }
1820
1821 if (!*args[cur_arg + 1]) {
1822 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1823 file, linenum, args[cur_arg]);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001829 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001830
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001831 if (curproxy->listen->luid <= 0) {
1832 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001833 file, linenum);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001838 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1839 if (node) {
1840 l = container_of(node, struct listener, conf.id);
1841 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1842 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
1845 }
1846 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1847
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001848 cur_arg += 2;
1849 continue;
1850 }
1851
Emeric Bruned760922010-10-22 17:59:25 +02001852 if (!strcmp(args[cur_arg], "mode")) {
1853
1854 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1855 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1856 file, linenum, args[0], args[cur_arg]);
1857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
1859 }
1860
1861 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1862
1863 cur_arg += 2;
1864 continue;
1865 }
1866
1867 if (!strcmp(args[cur_arg], "uid")) {
1868
1869 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1870 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1871 file, linenum, args[0], args[cur_arg]);
1872 err_code |= ERR_ALERT | ERR_FATAL;
1873 goto out;
1874 }
1875
1876 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1877 cur_arg += 2;
1878 continue;
1879 }
1880
1881 if (!strcmp(args[cur_arg], "gid")) {
1882
1883 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1884 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1885 file, linenum, args[0], args[cur_arg]);
1886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
1888 }
1889
1890 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1891 cur_arg += 2;
1892 continue;
1893 }
1894
1895 if (!strcmp(args[cur_arg], "user")) {
1896 struct passwd *user;
1897
1898 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1899 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1900 file, linenum, args[0], args[cur_arg]);
1901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
1903 }
1904 user = getpwnam(args[cur_arg + 1]);
1905 if (!user) {
1906 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1907 file, linenum, args[0], args[cur_arg + 1 ]);
1908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
1910 }
1911
1912 curproxy->listen->perm.ux.uid = user->pw_uid;
1913 cur_arg += 2;
1914 continue;
1915 }
1916
1917 if (!strcmp(args[cur_arg], "group")) {
1918 struct group *group;
1919
1920 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1921 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1922 file, linenum, args[0], args[cur_arg]);
1923 err_code |= ERR_ALERT | ERR_FATAL;
1924 goto out;
1925 }
1926 group = getgrnam(args[cur_arg + 1]);
1927 if (!group) {
1928 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1929 file, linenum, args[0], args[cur_arg + 1 ]);
1930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
1932 }
1933
1934 curproxy->listen->perm.ux.gid = group->gr_gid;
1935 cur_arg += 2;
1936 continue;
1937 }
1938
Willy Tarreaub48f9582011-09-05 01:17:06 +02001939 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 +01001940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001943 }
Willy Tarreau93893792009-07-23 13:19:11 +02001944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 }
1946 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1947 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1948 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001953 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 /* flush useless bits */
1957 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001960 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001961 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001963
Willy Tarreau1c47f852006-07-09 08:22:27 +02001964 if (!*args[1]) {
1965 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001969 }
1970
Willy Tarreaua534fea2008-08-03 12:19:50 +02001971 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001972 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001973 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001974 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001975 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1976
Willy Tarreau93893792009-07-23 13:19:11 +02001977 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1980 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1981 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1982 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1983 else {
1984 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 }
1988 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001989 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001990 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001991
1992 if (curproxy == &defproxy) {
1993 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1994 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001995 err_code |= ERR_ALERT | ERR_FATAL;
1996 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001997 }
1998
1999 if (!*args[1]) {
2000 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2001 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002004 }
2005
2006 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002007 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002008
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002009 if (curproxy->uuid <= 0) {
2010 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002011 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002014 }
2015
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002016 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2017 if (node) {
2018 struct proxy *target = container_of(node, struct proxy, conf.id);
2019 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2020 file, linenum, proxy_type_str(curproxy), curproxy->id,
2021 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2022 err_code |= ERR_ALERT | ERR_FATAL;
2023 goto out;
2024 }
2025 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002026 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002027 else if (!strcmp(args[0], "description")) {
2028 int i, len=0;
2029 char *d;
2030
Cyril Bonté99ed3272010-01-24 23:29:44 +01002031 if (curproxy == &defproxy) {
2032 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2033 file, linenum, args[0]);
2034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
2036 }
2037
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002038 if (!*args[1]) {
2039 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2040 file, linenum, args[0]);
2041 return -1;
2042 }
2043
2044 for(i=1; *args[i]; i++)
2045 len += strlen(args[i])+1;
2046
2047 d = (char *)calloc(1, len);
2048 curproxy->desc = d;
2049
2050 d += sprintf(d, "%s", args[1]);
2051 for(i=2; *args[i]; i++)
2052 d += sprintf(d, " %s", args[i]);
2053
2054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002055 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2056 curproxy->state = PR_STSTOPPED;
2057 }
2058 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2059 curproxy->state = PR_STNEW;
2060 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002061 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2062 int cur_arg = 1;
2063 unsigned int set = 0;
2064
2065 while (*args[cur_arg]) {
2066 int u;
2067 if (strcmp(args[cur_arg], "all") == 0) {
2068 set = 0;
2069 break;
2070 }
2071 else if (strcmp(args[cur_arg], "odd") == 0) {
2072 set |= 0x55555555;
2073 }
2074 else if (strcmp(args[cur_arg], "even") == 0) {
2075 set |= 0xAAAAAAAA;
2076 }
2077 else {
2078 u = str2uic(args[cur_arg]);
2079 if (u < 1 || u > 32) {
2080 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002084 }
2085 if (u > global.nbproc) {
2086 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2087 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002088 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002089 }
2090 set |= 1 << (u - 1);
2091 }
2092 cur_arg++;
2093 }
2094 curproxy->bind_proc = set;
2095 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002096 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002097 if (curproxy == &defproxy) {
2098 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002101 }
2102
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002103 err = invalid_char(args[1]);
2104 if (err) {
2105 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2106 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002108 }
2109
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002110 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2111 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2112 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002115 }
2116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2118 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119
Willy Tarreau977b8e42006-12-29 14:19:17 +01002120 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002122
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 if (*(args[1]) == 0) {
2124 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2125 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002129
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002130 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002131 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002132 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002133 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002134 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 curproxy->cookie_name = strdup(args[1]);
2136 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002137
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 cur_arg = 2;
2139 while (*(args[cur_arg])) {
2140 if (!strcmp(args[cur_arg], "rewrite")) {
2141 curproxy->options |= PR_O_COOK_RW;
2142 }
2143 else if (!strcmp(args[cur_arg], "indirect")) {
2144 curproxy->options |= PR_O_COOK_IND;
2145 }
2146 else if (!strcmp(args[cur_arg], "insert")) {
2147 curproxy->options |= PR_O_COOK_INS;
2148 }
2149 else if (!strcmp(args[cur_arg], "nocache")) {
2150 curproxy->options |= PR_O_COOK_NOC;
2151 }
2152 else if (!strcmp(args[cur_arg], "postonly")) {
2153 curproxy->options |= PR_O_COOK_POST;
2154 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002155 else if (!strcmp(args[cur_arg], "preserve")) {
2156 curproxy->options2 |= PR_O2_COOK_PSV;
2157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 else if (!strcmp(args[cur_arg], "prefix")) {
2159 curproxy->options |= PR_O_COOK_PFX;
2160 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002161 else if (!strcmp(args[cur_arg], "domain")) {
2162 if (!*args[cur_arg + 1]) {
2163 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2164 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002167 }
2168
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002169 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002170 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002171 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2172 " dots nor does not start with a dot."
2173 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002174 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002175 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002176 }
2177
2178 err = invalid_domainchar(args[cur_arg + 1]);
2179 if (err) {
2180 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2181 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002184 }
2185
Willy Tarreau68a897b2009-12-03 23:28:34 +01002186 if (!curproxy->cookie_domain) {
2187 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2188 } else {
2189 /* one domain was already specified, add another one by
2190 * building the string which will be returned along with
2191 * the cookie.
2192 */
2193 char *new_ptr;
2194 int new_len = strlen(curproxy->cookie_domain) +
2195 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2196 new_ptr = malloc(new_len);
2197 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2198 free(curproxy->cookie_domain);
2199 curproxy->cookie_domain = new_ptr;
2200 }
Willy Tarreau31936852010-10-06 16:59:56 +02002201 cur_arg++;
2202 }
2203 else if (!strcmp(args[cur_arg], "maxidle")) {
2204 unsigned int maxidle;
2205 const char *res;
2206
2207 if (!*args[cur_arg + 1]) {
2208 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2209 file, linenum, args[cur_arg]);
2210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
2212 }
2213
2214 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2215 if (res) {
2216 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2217 file, linenum, *res, args[cur_arg]);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
2220 }
2221 curproxy->cookie_maxidle = maxidle;
2222 cur_arg++;
2223 }
2224 else if (!strcmp(args[cur_arg], "maxlife")) {
2225 unsigned int maxlife;
2226 const char *res;
2227
2228 if (!*args[cur_arg + 1]) {
2229 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2230 file, linenum, args[cur_arg]);
2231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
2233 }
2234
2235 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2236 if (res) {
2237 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2238 file, linenum, *res, args[cur_arg]);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002243 cur_arg++;
2244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002246 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 +02002247 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
2251 cur_arg++;
2252 }
2253 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2254 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2255 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 }
2258
2259 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2260 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2261 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002264
2265 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2266 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2267 file, linenum);
2268 err_code |= ERR_ALERT | ERR_FATAL;
2269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002271 else if (!strcmp(args[0], "persist")) { /* persist */
2272 if (*(args[1]) == 0) {
2273 Alert("parsing [%s:%d] : missing persist method.\n",
2274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002277 }
2278
2279 if (!strncmp(args[1], "rdp-cookie", 10)) {
2280 curproxy->options2 |= PR_O2_RDPC_PRST;
2281
Emeric Brunb982a3d2010-01-04 15:45:53 +01002282 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002283 const char *beg, *end;
2284
2285 beg = args[1] + 11;
2286 end = strchr(beg, ')');
2287
2288 if (!end || end == beg) {
2289 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2290 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002293 }
2294
2295 free(curproxy->rdp_cookie_name);
2296 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2297 curproxy->rdp_cookie_len = end-beg;
2298 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002299 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002300 free(curproxy->rdp_cookie_name);
2301 curproxy->rdp_cookie_name = strdup("msts");
2302 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2303 }
2304 else { /* syntax */
2305 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2306 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002309 }
2310 }
2311 else {
2312 Alert("parsing [%s:%d] : unknown persist method.\n",
2313 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002316 }
2317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002319 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002321 if (curproxy == &defproxy) {
2322 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
2325 }
2326
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002331 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 }
2336 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002337 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 curproxy->appsession_name = strdup(args[1]);
2339 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2340 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002341 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2342 if (err) {
2343 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2344 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002347 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002348 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002349
Willy Tarreau51041c72007-09-09 21:56:53 +02002350 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2351 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_ABORT;
2353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002355
2356 cur_arg = 6;
2357 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002358 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2359 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002360 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002361 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002362 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002363 } else if (!strcmp(args[cur_arg], "prefix")) {
2364 curproxy->options2 |= PR_O2_AS_PFX;
2365 } else if (!strcmp(args[cur_arg], "mode")) {
2366 if (!*args[cur_arg + 1]) {
2367 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2368 file, linenum, args[0], args[cur_arg]);
2369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
2371 }
2372
2373 cur_arg++;
2374 if (!strcmp(args[cur_arg], "query-string")) {
2375 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2376 curproxy->options2 |= PR_O2_AS_M_QS;
2377 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2378 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2379 curproxy->options2 |= PR_O2_AS_M_PP;
2380 } else {
2381 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
2384 }
2385 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002386 cur_arg++;
2387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 } /* Url App Session */
2389 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002390 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002392
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002394 if (curproxy == &defproxy) {
2395 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
2398 }
2399
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 if (*(args[4]) == 0) {
2401 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2402 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002406 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 curproxy->capture_name = strdup(args[2]);
2408 curproxy->capture_namelen = strlen(curproxy->capture_name);
2409 curproxy->capture_len = atol(args[4]);
2410 if (curproxy->capture_len >= CAPTURE_LEN) {
2411 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2412 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 curproxy->capture_len = CAPTURE_LEN - 1;
2415 }
2416 curproxy->to_log |= LW_COOKIE;
2417 }
2418 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2419 struct cap_hdr *hdr;
2420
2421 if (curproxy == &defproxy) {
2422 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 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 }
2426
2427 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2428 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2429 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433
2434 hdr = calloc(sizeof(struct cap_hdr), 1);
2435 hdr->next = curproxy->req_cap;
2436 hdr->name = strdup(args[3]);
2437 hdr->namelen = strlen(args[3]);
2438 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002439 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 hdr->index = curproxy->nb_req_cap++;
2441 curproxy->req_cap = hdr;
2442 curproxy->to_log |= LW_REQHDR;
2443 }
2444 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2445 struct cap_hdr *hdr;
2446
2447 if (curproxy == &defproxy) {
2448 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 +02002449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
2452
2453 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2454 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2455 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
2459 hdr = calloc(sizeof(struct cap_hdr), 1);
2460 hdr->next = curproxy->rsp_cap;
2461 hdr->name = strdup(args[3]);
2462 hdr->namelen = strlen(args[3]);
2463 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002464 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 hdr->index = curproxy->nb_rsp_cap++;
2466 curproxy->rsp_cap = hdr;
2467 curproxy->to_log |= LW_RSPHDR;
2468 }
2469 else {
2470 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2471 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 }
2475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002477 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002479
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 if (*(args[1]) == 0) {
2481 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
2486 curproxy->conn_retries = atol(args[1]);
2487 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002488 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002489 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002490
2491 if (curproxy == &defproxy) {
2492 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
Willy Tarreauff011f22011-01-06 17:51:27 +01002497 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 +01002498 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2499 file, linenum, args[0]);
2500 err_code |= ERR_WARN;
2501 }
2502
Willy Tarreauff011f22011-01-06 17:51:27 +01002503 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002504
Willy Tarreauff011f22011-01-06 17:51:27 +01002505 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002506 err_code |= ERR_ALERT | ERR_ABORT;
2507 goto out;
2508 }
2509
Willy Tarreauff011f22011-01-06 17:51:27 +01002510 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2511 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002512 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002513 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2514 /* set the header name and length into the proxy structure */
2515 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2516 err_code |= ERR_WARN;
2517
2518 if (!*args[1]) {
2519 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2520 file, linenum, args[0]);
2521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
2523 }
2524
2525 /* set the desired header name */
2526 free(curproxy->server_id_hdr_name);
2527 curproxy->server_id_hdr_name = strdup(args[1]);
2528 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2529 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002530 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002531 if (curproxy == &defproxy) {
2532 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002535 }
2536
Willy Tarreauef6494c2010-01-28 17:12:36 +01002537 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002538 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2539 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002542 }
2543
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002544 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2545 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2546 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002549 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002550
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002551 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002552 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002553 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002554 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 struct redirect_rule *rule;
2556 int cur_arg;
2557 int type = REDIRECT_TYPE_NONE;
2558 int code = 302;
2559 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002560 char *cookie = NULL;
2561 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002562 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563
Cyril Bonté99ed3272010-01-24 23:29:44 +01002564 if (curproxy == &defproxy) {
2565 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
2568 }
2569
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002570 cur_arg = 1;
2571 while (*(args[cur_arg])) {
2572 if (!strcmp(args[cur_arg], "location")) {
2573 if (!*args[cur_arg + 1]) {
2574 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2575 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002578 }
2579
2580 type = REDIRECT_TYPE_LOCATION;
2581 cur_arg++;
2582 destination = args[cur_arg];
2583 }
2584 else if (!strcmp(args[cur_arg], "prefix")) {
2585 if (!*args[cur_arg + 1]) {
2586 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2587 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002590 }
2591
2592 type = REDIRECT_TYPE_PREFIX;
2593 cur_arg++;
2594 destination = args[cur_arg];
2595 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002596 else if (!strcmp(args[cur_arg], "set-cookie")) {
2597 if (!*args[cur_arg + 1]) {
2598 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2599 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002602 }
2603
2604 cur_arg++;
2605 cookie = args[cur_arg];
2606 cookie_set = 1;
2607 }
2608 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2609 if (!*args[cur_arg + 1]) {
2610 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2611 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002614 }
2615
2616 cur_arg++;
2617 cookie = args[cur_arg];
2618 cookie_set = 0;
2619 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002620 else if (!strcmp(args[cur_arg],"code")) {
2621 if (!*args[cur_arg + 1]) {
2622 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 }
2627 cur_arg++;
2628 code = atol(args[cur_arg]);
2629 if (code < 301 || code > 303) {
2630 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2631 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002634 }
2635 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002636 else if (!strcmp(args[cur_arg],"drop-query")) {
2637 flags |= REDIRECT_FLAG_DROP_QS;
2638 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002639 else if (!strcmp(args[cur_arg],"append-slash")) {
2640 flags |= REDIRECT_FLAG_APPEND_SLASH;
2641 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002642 else if (strcmp(args[cur_arg], "if") == 0 ||
2643 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002644 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002646 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2647 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002651 break;
2652 }
2653 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002654 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 +02002655 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002658 }
2659 cur_arg++;
2660 }
2661
2662 if (type == REDIRECT_TYPE_NONE) {
2663 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2664 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002667 }
2668
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002669 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2670 rule->cond = cond;
2671 rule->rdr_str = strdup(destination);
2672 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002673 if (cookie) {
2674 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002675 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002676 */
2677 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002678 if (cookie_set) {
2679 rule->cookie_str = malloc(rule->cookie_len + 10);
2680 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2681 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2682 rule->cookie_len += 9;
2683 } else {
2684 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002685 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002686 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2687 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002688 }
2689 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002690 rule->type = type;
2691 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002692 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002693 LIST_INIT(&rule->list);
2694 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002695 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2696 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002697 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002698 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002699 struct switching_rule *rule;
2700
Willy Tarreaub099aca2008-10-12 17:26:37 +02002701 if (curproxy == &defproxy) {
2702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002705 }
2706
Willy Tarreau55ea7572007-06-17 19:56:27 +02002707 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002709
2710 if (*(args[1]) == 0) {
2711 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002714 }
2715
Willy Tarreauef6494c2010-01-28 17:12:36 +01002716 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002717 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002721 }
2722
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002723 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2724 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2725 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002728 }
2729
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002730 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002731
Willy Tarreau55ea7572007-06-17 19:56:27 +02002732 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2733 rule->cond = cond;
2734 rule->be.name = strdup(args[1]);
2735 LIST_INIT(&rule->list);
2736 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2737 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002738 else if (strcmp(args[0], "use-server") == 0) {
2739 struct server_rule *rule;
2740
2741 if (curproxy == &defproxy) {
2742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
2745 }
2746
2747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2748 err_code |= ERR_WARN;
2749
2750 if (*(args[1]) == 0) {
2751 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
2756 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2757 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2758 file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002763 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2764 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2765 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
2770 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2771
2772 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2773 rule->cond = cond;
2774 rule->srv.name = strdup(args[1]);
2775 LIST_INIT(&rule->list);
2776 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2777 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2778 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002779 else if ((!strcmp(args[0], "force-persist")) ||
2780 (!strcmp(args[0], "ignore-persist"))) {
2781 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002782
2783 if (curproxy == &defproxy) {
2784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
2787 }
2788
2789 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2790 err_code |= ERR_WARN;
2791
Willy Tarreauef6494c2010-01-28 17:12:36 +01002792 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002793 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2794 file, linenum, args[0]);
2795 err_code |= ERR_ALERT | ERR_FATAL;
2796 goto out;
2797 }
2798
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002799 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2800 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2801 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804 }
2805
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002806 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002807
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002808 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002809 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002810 if (!strcmp(args[0], "force-persist")) {
2811 rule->type = PERSIST_TYPE_FORCE;
2812 } else {
2813 rule->type = PERSIST_TYPE_IGNORE;
2814 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002815 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002816 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002817 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002818 else if (!strcmp(args[0], "stick-table")) {
2819 int myidx = 1;
2820
Emeric Brun32da3c42010-09-23 18:39:19 +02002821 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002822 curproxy->table.type = (unsigned int)-1;
2823 while (*args[myidx]) {
2824 const char *err;
2825
2826 if (strcmp(args[myidx], "size") == 0) {
2827 myidx++;
2828 if (!*(args[myidx])) {
2829 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2830 file, linenum, args[myidx-1]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2835 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2836 file, linenum, *err, args[myidx-1]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002840 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002841 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002842 else if (strcmp(args[myidx], "peers") == 0) {
2843 myidx++;
2844 if (!*(args[myidx])) {
2845 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2846 file, linenum, args[myidx-1]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
2850 curproxy->table.peers.name = strdup(args[myidx++]);
2851 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002852 else if (strcmp(args[myidx], "expire") == 0) {
2853 myidx++;
2854 if (!*(args[myidx])) {
2855 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2856 file, linenum, args[myidx-1]);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2861 if (err) {
2862 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2863 file, linenum, *err, args[myidx-1]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002868 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002869 }
2870 else if (strcmp(args[myidx], "nopurge") == 0) {
2871 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002872 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002873 }
2874 else if (strcmp(args[myidx], "type") == 0) {
2875 myidx++;
2876 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2877 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2878 file, linenum, args[myidx]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002882 /* myidx already points to next arg */
2883 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002884 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002885 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002886 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002887
2888 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002889 nw = args[myidx];
2890 while (*nw) {
2891 /* the "store" keyword supports a comma-separated list */
2892 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002893 sa = NULL; /* store arg */
2894 while (*nw && *nw != ',') {
2895 if (*nw == '(') {
2896 *nw = 0;
2897 sa = ++nw;
2898 while (*nw != ')') {
2899 if (!*nw) {
2900 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2901 file, linenum, args[0], cw);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905 nw++;
2906 }
2907 *nw = '\0';
2908 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002909 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002910 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002911 if (*nw)
2912 *nw++ = '\0';
2913 type = stktable_get_data_type(cw);
2914 if (type < 0) {
2915 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2916 file, linenum, args[0], cw);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
Willy Tarreauac782882010-06-20 10:41:54 +02002920
2921 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2922 switch (err) {
2923 case PE_NONE: break;
2924 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002925 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002928 break;
2929
2930 case PE_ARG_MISSING:
2931 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2932 file, linenum, args[0], cw);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935
2936 case PE_ARG_NOT_USED:
2937 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2938 file, linenum, args[0], cw);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941
2942 default:
2943 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2944 file, linenum, args[0], cw);
2945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002947 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002948 }
2949 myidx++;
2950 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002951 else {
2952 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2953 file, linenum, args[myidx]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002957 }
2958
2959 if (!curproxy->table.size) {
2960 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2961 file, linenum);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
2966 if (curproxy->table.type == (unsigned int)-1) {
2967 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2968 file, linenum);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972 }
2973 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002974 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002975 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002976 int myidx = 0;
2977 const char *name = NULL;
2978 int flags;
2979
2980 if (curproxy == &defproxy) {
2981 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
2985
2986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2987 err_code |= ERR_WARN;
2988 goto out;
2989 }
2990
2991 myidx++;
2992 if ((strcmp(args[myidx], "store") == 0) ||
2993 (strcmp(args[myidx], "store-request") == 0)) {
2994 myidx++;
2995 flags = STK_IS_STORE;
2996 }
2997 else if (strcmp(args[myidx], "store-response") == 0) {
2998 myidx++;
2999 flags = STK_IS_STORE | STK_ON_RSP;
3000 }
3001 else if (strcmp(args[myidx], "match") == 0) {
3002 myidx++;
3003 flags = STK_IS_MATCH;
3004 }
3005 else if (strcmp(args[myidx], "on") == 0) {
3006 myidx++;
3007 flags = STK_IS_MATCH | STK_IS_STORE;
3008 }
3009 else {
3010 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013 }
3014
3015 if (*(args[myidx]) == 0) {
3016 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020
David du Colombier7af46052012-05-16 14:16:48 +02003021 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003022 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003023 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
3027
3028 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003029 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3031 file, linenum, args[0], expr->fetch->kw);
3032 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003033 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003034 goto out;
3035 }
3036 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003037 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3039 file, linenum, args[0], expr->fetch->kw);
3040 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003041 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003042 goto out;
3043 }
3044 }
3045
3046 if (strcmp(args[myidx], "table") == 0) {
3047 myidx++;
3048 name = args[myidx++];
3049 }
3050
Willy Tarreauef6494c2010-01-28 17:12:36 +01003051 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003052 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3053 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3054 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003055 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003056 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003057 goto out;
3058 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003060 else if (*(args[myidx])) {
3061 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3062 file, linenum, args[0], args[myidx]);
3063 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003064 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003065 goto out;
3066 }
Emeric Brun97679e72010-09-23 17:56:44 +02003067 if (flags & STK_ON_RSP)
3068 err_code |= warnif_cond_requires_req(cond, file, linenum);
3069 else
3070 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003071
Emeric Brunb982a3d2010-01-04 15:45:53 +01003072 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3073 rule->cond = cond;
3074 rule->expr = expr;
3075 rule->flags = flags;
3076 rule->table.name = name ? strdup(name) : NULL;
3077 LIST_INIT(&rule->list);
3078 if (flags & STK_ON_RSP)
3079 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3080 else
3081 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003084 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003086
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3088 curproxy->uri_auth = NULL; /* we must detach from the default config */
3089
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003090 if (!*args[1]) {
3091 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003092 } else if (!strcmp(args[1], "admin")) {
3093 struct stats_admin_rule *rule;
3094
3095 if (curproxy == &defproxy) {
3096 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3102 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3103 err_code |= ERR_ALERT | ERR_ABORT;
3104 goto out;
3105 }
3106
3107 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3108 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3109 file, linenum, args[0], args[1]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003113 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3114 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3115 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
3120 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3121
3122 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3123 rule->cond = cond;
3124 LIST_INIT(&rule->list);
3125 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 } else if (!strcmp(args[1], "uri")) {
3127 if (*(args[2]) == 0) {
3128 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3132 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
3136 } else if (!strcmp(args[1], "realm")) {
3137 if (*(args[2]) == 0) {
3138 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003146 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003147 unsigned interval;
3148
3149 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3150 if (err) {
3151 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3152 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003155 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3156 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_ABORT;
3158 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003159 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003160 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003161 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003162
3163 if (curproxy == &defproxy) {
3164 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167 }
3168
3169 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3170 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
3173 }
3174
Willy Tarreauff011f22011-01-06 17:51:27 +01003175 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3176 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003177 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3178 file, linenum, args[0]);
3179 err_code |= ERR_WARN;
3180 }
3181
Willy Tarreauff011f22011-01-06 17:51:27 +01003182 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003183
Willy Tarreauff011f22011-01-06 17:51:27 +01003184 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003185 err_code |= ERR_ALERT | ERR_ABORT;
3186 goto out;
3187 }
3188
Willy Tarreauff011f22011-01-06 17:51:27 +01003189 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3190 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003191
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 } else if (!strcmp(args[1], "auth")) {
3193 if (*(args[2]) == 0) {
3194 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202 } else if (!strcmp(args[1], "scope")) {
3203 if (*(args[2]) == 0) {
3204 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 }
3212 } else if (!strcmp(args[1], "enable")) {
3213 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3214 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_ABORT;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003218 } else if (!strcmp(args[1], "hide-version")) {
3219 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3220 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_ABORT;
3222 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003223 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003224 } else if (!strcmp(args[1], "show-legends")) {
3225 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3226 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
3229 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003230 } else if (!strcmp(args[1], "show-node")) {
3231
3232 if (*args[2]) {
3233 int i;
3234 char c;
3235
3236 for (i=0; args[2][i]; i++) {
3237 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003238 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3239 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003240 break;
3241 }
3242
3243 if (!i || args[2][i]) {
3244 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3245 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3246 file, linenum, args[0], args[1]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250 }
3251
3252 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3253 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
3256 }
3257 } else if (!strcmp(args[1], "show-desc")) {
3258 char *desc = NULL;
3259
3260 if (*args[2]) {
3261 int i, len=0;
3262 char *d;
3263
3264 for(i=2; *args[i]; i++)
3265 len += strlen(args[i])+1;
3266
3267 desc = d = (char *)calloc(1, len);
3268
3269 d += sprintf(d, "%s", args[2]);
3270 for(i=3; *args[i]; i++)
3271 d += sprintf(d, " %s", args[i]);
3272 }
3273
3274 if (!*args[2] && !global.desc)
3275 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3276 file, linenum, args[1]);
3277 else {
3278 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3279 free(desc);
3280 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3281 err_code |= ERR_ALERT | ERR_ABORT;
3282 goto out;
3283 }
3284 free(desc);
3285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003287stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003288 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 +01003289 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293 }
3294 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003295 int optnum;
3296
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003297 if (*(args[1]) == '\0') {
3298 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003303
3304 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3305 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003306 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3307 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3308 file, linenum, cfg_opts[optnum].name);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
3311 }
Willy Tarreau93893792009-07-23 13:19:11 +02003312 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3313 err_code |= ERR_WARN;
3314 goto out;
3315 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003316
Willy Tarreau3842f002009-06-14 11:39:52 +02003317 curproxy->no_options &= ~cfg_opts[optnum].val;
3318 curproxy->options &= ~cfg_opts[optnum].val;
3319
3320 switch (kwm) {
3321 case KWM_STD:
3322 curproxy->options |= cfg_opts[optnum].val;
3323 break;
3324 case KWM_NO:
3325 curproxy->no_options |= cfg_opts[optnum].val;
3326 break;
3327 case KWM_DEF: /* already cleared */
3328 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003329 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003330
Willy Tarreau93893792009-07-23 13:19:11 +02003331 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003332 }
3333 }
3334
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003335 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3336 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003337 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3338 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3339 file, linenum, cfg_opts2[optnum].name);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
Willy Tarreau93893792009-07-23 13:19:11 +02003343 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3344 err_code |= ERR_WARN;
3345 goto out;
3346 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003347
Willy Tarreau3842f002009-06-14 11:39:52 +02003348 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3349 curproxy->options2 &= ~cfg_opts2[optnum].val;
3350
3351 switch (kwm) {
3352 case KWM_STD:
3353 curproxy->options2 |= cfg_opts2[optnum].val;
3354 break;
3355 case KWM_NO:
3356 curproxy->no_options2 |= cfg_opts2[optnum].val;
3357 break;
3358 case KWM_DEF: /* already cleared */
3359 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003360 }
Willy Tarreau93893792009-07-23 13:19:11 +02003361 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003362 }
3363 }
3364
Willy Tarreau3842f002009-06-14 11:39:52 +02003365 if (kwm != KWM_STD) {
3366 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003367 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003370 }
3371
Emeric Brun3a058f32009-06-30 18:26:00 +02003372 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003373 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003375 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003376 if (*(args[2]) != '\0') {
3377 if (!strcmp(args[2], "clf")) {
3378 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003379 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003380 } else {
3381 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003384 }
3385 }
William Lallemand1d705562012-03-12 12:46:41 +01003386 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
Emeric Brun3a058f32009-06-30 18:26:00 +02003387 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003388 else if (!strcmp(args[1], "tcplog")) {
3389 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 /* generate a detailed TCP log */
William Lallemandbddd4fd2012-02-27 11:23:10 +01003391 logformat = default_tcp_log_format;
William Lallemand1d705562012-03-12 12:46:41 +01003392 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
William Lallemandbddd4fd2012-02-27 11:23:10 +01003393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 else if (!strcmp(args[1], "tcpka")) {
3395 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003396 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003398
3399 if (curproxy->cap & PR_CAP_FE)
3400 curproxy->options |= PR_O_TCP_CLI_KA;
3401 if (curproxy->cap & PR_CAP_BE)
3402 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003405 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_WARN;
3407
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003409 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003410 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003411 curproxy->options2 &= ~PR_O2_CHK_ANY;
3412 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 if (!*args[2]) { /* no argument */
3414 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3415 curproxy->check_len = strlen(DEF_CHECK_REQ);
3416 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003417 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 curproxy->check_req = (char *)malloc(reqlen);
3419 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003420 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003422 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 if (*args[4])
3424 reqlen += strlen(args[4]);
3425 else
3426 reqlen += strlen("HTTP/1.0");
3427
3428 curproxy->check_req = (char *)malloc(reqlen);
3429 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003430 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003432 }
3433 else if (!strcmp(args[1], "ssl-hello-chk")) {
3434 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003435 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003437
Willy Tarreaua534fea2008-08-03 12:19:50 +02003438 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003439 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003440 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003441 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
Willy Tarreau23677902007-05-08 23:50:35 +02003443 else if (!strcmp(args[1], "smtpchk")) {
3444 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003445 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003446 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003447 curproxy->options2 &= ~PR_O2_CHK_ANY;
3448 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003449
3450 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3451 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3452 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3453 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3454 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3455 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3456 curproxy->check_req = (char *)malloc(reqlen);
3457 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3458 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3459 } else {
3460 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3461 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3462 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3463 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3464 }
3465 }
3466 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003467 else if (!strcmp(args[1], "pgsql-check")) {
3468 /* use PostgreSQL request to check servers' health */
3469 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3470 err_code |= ERR_WARN;
3471
3472 free(curproxy->check_req);
3473 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003474 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003475 curproxy->options2 |= PR_O2_PGSQL_CHK;
3476
3477 if (*(args[2])) {
3478 int cur_arg = 2;
3479
3480 while (*(args[cur_arg])) {
3481 if (strcmp(args[cur_arg], "user") == 0) {
3482 char * packet;
3483 uint32_t packet_len;
3484 uint32_t pv;
3485
3486 /* suboption header - needs additional argument for it */
3487 if (*(args[cur_arg+1]) == 0) {
3488 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3489 file, linenum, args[0], args[1], args[cur_arg]);
3490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
3492 }
3493
3494 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3495 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3496 pv = htonl(0x30000); /* protocol version 3.0 */
3497
3498 packet = (char*) calloc(1, packet_len);
3499
3500 memcpy(packet + 4, &pv, 4);
3501
3502 /* copy "user" */
3503 memcpy(packet + 8, "user", 4);
3504
3505 /* copy username */
3506 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3507
3508 free(curproxy->check_req);
3509 curproxy->check_req = packet;
3510 curproxy->check_len = packet_len;
3511
3512 packet_len = htonl(packet_len);
3513 memcpy(packet, &packet_len, 4);
3514 cur_arg += 2;
3515 } else {
3516 /* unknown suboption - catchall */
3517 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3518 file, linenum, args[0], args[1]);
3519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
3521 }
3522 } /* end while loop */
3523 }
3524 }
3525
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003526 else if (!strcmp(args[1], "redis-check")) {
3527 /* use REDIS PING request to check servers' health */
3528 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3529 err_code |= ERR_WARN;
3530
3531 free(curproxy->check_req);
3532 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003533 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003534 curproxy->options2 |= PR_O2_REDIS_CHK;
3535
3536 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3537 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3538 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3539 }
3540
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003541 else if (!strcmp(args[1], "mysql-check")) {
3542 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003543 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3544 err_code |= ERR_WARN;
3545
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003546 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003547 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003548 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003549 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003550
3551 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3552 * const char mysql40_client_auth_pkt[] = {
3553 * "\x0e\x00\x00" // packet length
3554 * "\x01" // packet number
3555 * "\x00\x00" // client capabilities
3556 * "\x00\x00\x01" // max packet
3557 * "haproxy\x00" // username (null terminated string)
3558 * "\x00" // filler (always 0x00)
3559 * "\x01\x00\x00" // packet length
3560 * "\x00" // packet number
3561 * "\x01" // COM_QUIT command
3562 * };
3563 */
3564
3565 if (*(args[2])) {
3566 int cur_arg = 2;
3567
3568 while (*(args[cur_arg])) {
3569 if (strcmp(args[cur_arg], "user") == 0) {
3570 char *mysqluser;
3571 int packetlen, reqlen, userlen;
3572
3573 /* suboption header - needs additional argument for it */
3574 if (*(args[cur_arg+1]) == 0) {
3575 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3576 file, linenum, args[0], args[1], args[cur_arg]);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
3580 mysqluser = args[cur_arg + 1];
3581 userlen = strlen(mysqluser);
3582 packetlen = userlen + 7;
3583 reqlen = packetlen + 9;
3584
3585 free(curproxy->check_req);
3586 curproxy->check_req = (char *)calloc(1, reqlen);
3587 curproxy->check_len = reqlen;
3588
3589 snprintf(curproxy->check_req, 4, "%c%c%c",
3590 ((unsigned char) packetlen & 0xff),
3591 ((unsigned char) (packetlen >> 8) & 0xff),
3592 ((unsigned char) (packetlen >> 16) & 0xff));
3593
3594 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003595 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003596 curproxy->check_req[8] = 1;
3597 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3598 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3599 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3600 cur_arg += 2;
3601 } else {
3602 /* unknown suboption - catchall */
3603 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3604 file, linenum, args[0], args[1]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 } /* end while loop */
3609 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003610 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003611 else if (!strcmp(args[1], "ldap-check")) {
3612 /* use LDAP request to check servers' health */
3613 free(curproxy->check_req);
3614 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003615 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003616 curproxy->options2 |= PR_O2_LDAP_CHK;
3617
3618 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3619 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3620 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3621 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003622 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003623 int cur_arg;
3624
3625 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3626 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003627 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003628
Willy Tarreau87cf5142011-08-19 22:57:24 +02003629 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003630
3631 free(curproxy->fwdfor_hdr_name);
3632 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3633 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3634
3635 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3636 cur_arg = 2;
3637 while (*(args[cur_arg])) {
3638 if (!strcmp(args[cur_arg], "except")) {
3639 /* suboption except - needs additional argument for it */
3640 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3641 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3642 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003645 }
3646 /* flush useless bits */
3647 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003648 cur_arg += 2;
3649 } else if (!strcmp(args[cur_arg], "header")) {
3650 /* suboption header - needs additional argument for it */
3651 if (*(args[cur_arg+1]) == 0) {
3652 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3653 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003656 }
3657 free(curproxy->fwdfor_hdr_name);
3658 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3659 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3660 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003661 } else if (!strcmp(args[cur_arg], "if-none")) {
3662 curproxy->options &= ~PR_O_FF_ALWAYS;
3663 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003664 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003666 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003667 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003670 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003671 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003672 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003673 else if (!strcmp(args[1], "originalto")) {
3674 int cur_arg;
3675
3676 /* insert x-original-to field, but not for the IP address listed as an except.
3677 * set default options (ie: bitfield, header name, etc)
3678 */
3679
3680 curproxy->options |= PR_O_ORGTO;
3681
3682 free(curproxy->orgto_hdr_name);
3683 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3684 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3685
Willy Tarreau87cf5142011-08-19 22:57:24 +02003686 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003687 cur_arg = 2;
3688 while (*(args[cur_arg])) {
3689 if (!strcmp(args[cur_arg], "except")) {
3690 /* suboption except - needs additional argument for it */
3691 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3692 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3693 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003696 }
3697 /* flush useless bits */
3698 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3699 cur_arg += 2;
3700 } else if (!strcmp(args[cur_arg], "header")) {
3701 /* suboption header - needs additional argument for it */
3702 if (*(args[cur_arg+1]) == 0) {
3703 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3704 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003707 }
3708 free(curproxy->orgto_hdr_name);
3709 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3710 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3711 cur_arg += 2;
3712 } else {
3713 /* unknown suboption - catchall */
3714 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3715 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003718 }
3719 } /* end while loop */
3720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 else {
3722 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 }
Willy Tarreau93893792009-07-23 13:19:11 +02003726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003728 else if (!strcmp(args[0], "default_backend")) {
3729 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003731
3732 if (*(args[1]) == 0) {
3733 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003736 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003737 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003738 curproxy->defbe.name = strdup(args[1]);
3739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003743
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003744 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3745 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 /* enable reconnections to dispatch */
3748 curproxy->options |= PR_O_REDISP;
3749 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003750 else if (!strcmp(args[0], "http-check")) {
3751 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003753
3754 if (strcmp(args[1], "disable-on-404") == 0) {
3755 /* enable a graceful server shutdown on an HTTP 404 response */
3756 curproxy->options |= PR_O_DISABLE404;
3757 }
Willy Tarreauef781042010-01-27 11:53:01 +01003758 else if (strcmp(args[1], "send-state") == 0) {
3759 /* enable emission of the apparent state of a server in HTTP checks */
3760 curproxy->options2 |= PR_O2_CHK_SNDST;
3761 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003762 else if (strcmp(args[1], "expect") == 0) {
3763 const char *ptr_arg;
3764 int cur_arg;
3765
3766 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3767 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
3770 }
3771
3772 cur_arg = 2;
3773 /* consider exclamation marks, sole or at the beginning of a word */
3774 while (*(ptr_arg = args[cur_arg])) {
3775 while (*ptr_arg == '!') {
3776 curproxy->options2 ^= PR_O2_EXP_INV;
3777 ptr_arg++;
3778 }
3779 if (*ptr_arg)
3780 break;
3781 cur_arg++;
3782 }
3783 /* now ptr_arg points to the beginning of a word past any possible
3784 * exclamation mark, and cur_arg is the argument which holds this word.
3785 */
3786 if (strcmp(ptr_arg, "status") == 0) {
3787 if (!*(args[cur_arg + 1])) {
3788 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3789 file, linenum, args[0], args[1], ptr_arg);
3790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
3792 }
3793 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003794 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003795 curproxy->expect_str = strdup(args[cur_arg + 1]);
3796 }
3797 else if (strcmp(ptr_arg, "string") == 0) {
3798 if (!*(args[cur_arg + 1])) {
3799 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3800 file, linenum, args[0], args[1], ptr_arg);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
3804 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003805 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003806 curproxy->expect_str = strdup(args[cur_arg + 1]);
3807 }
3808 else if (strcmp(ptr_arg, "rstatus") == 0) {
3809 if (!*(args[cur_arg + 1])) {
3810 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3811 file, linenum, args[0], args[1], ptr_arg);
3812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
3814 }
3815 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003816 free(curproxy->expect_str);
3817 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3818 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003819 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3820 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3821 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3822 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
3825 }
3826 }
3827 else if (strcmp(ptr_arg, "rstring") == 0) {
3828 if (!*(args[cur_arg + 1])) {
3829 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3830 file, linenum, args[0], args[1], ptr_arg);
3831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
3833 }
3834 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003835 free(curproxy->expect_str);
3836 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3837 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003838 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3839 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3840 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3841 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
3844 }
3845 }
3846 else {
3847 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3848 file, linenum, args[0], args[1], ptr_arg);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003853 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003854 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 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003857 }
3858 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003859 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003860 if (curproxy == &defproxy) {
3861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003864 }
3865
Willy Tarreaub80c2302007-11-30 20:51:32 +01003866 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003868
3869 if (strcmp(args[1], "fail") == 0) {
3870 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003871 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003872 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3873 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003876 }
3877
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003878 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3879 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3880 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003883 }
3884 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3885 }
3886 else {
3887 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003890 }
3891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892#ifdef TPROXY
3893 else if (!strcmp(args[0], "transparent")) {
3894 /* enable transparent proxy connections */
3895 curproxy->options |= PR_O_TRANSP;
3896 }
3897#endif
3898 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003901
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 if (*(args[1]) == 0) {
3903 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 }
3907 curproxy->maxconn = atol(args[1]);
3908 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003909 else if (!strcmp(args[0], "backlog")) { /* backlog */
3910 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003912
3913 if (*(args[1]) == 0) {
3914 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003917 }
3918 curproxy->backlog = atol(args[1]);
3919 }
Willy Tarreau86034312006-12-29 00:10:33 +01003920 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003921 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003922 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003923
Willy Tarreau86034312006-12-29 00:10:33 +01003924 if (*(args[1]) == 0) {
3925 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003928 }
3929 curproxy->fullconn = atol(args[1]);
3930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3932 if (*(args[1]) == 0) {
3933 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003937 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3938 if (err) {
3939 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3940 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003943 }
3944 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 }
3946 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003947 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 if (curproxy == &defproxy) {
3949 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003953 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003955
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 if (strchr(args[1], ':') == NULL) {
3957 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003961 sk = str2sa(args[1]);
3962 if (!sk) {
3963 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003968 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
3970 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003973
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003974 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3975 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003980 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3981 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3982 err_code |= ERR_WARN;
3983
3984 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3985 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3986 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3987 }
3988 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3989 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3990 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3991 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003992 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3993 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3994 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3995 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003996 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003997 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
4001 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004002 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004004 char *rport, *raddr;
4005 short realport = 0;
4006 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004008 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004013 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015
4016 if (!*args[2]) {
4017 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004022
4023 err = invalid_char(args[1]);
4024 if (err) {
4025 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4026 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004029 }
4030
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004032 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004033
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004034 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4035 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4036 err_code |= ERR_ALERT | ERR_ABORT;
4037 goto out;
4038 }
4039
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004040 /* the servers are linked backwards first */
4041 newsrv->next = curproxy->srv;
4042 curproxy->srv = newsrv;
4043 newsrv->proxy = curproxy;
4044 newsrv->conf.file = file;
4045 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046
Simon Hormanaf514952011-06-21 14:34:57 +09004047 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004048 LIST_INIT(&newsrv->pendconns);
4049 do_check = 0;
4050 newsrv->state = SRV_RUNNING; /* early server setup */
4051 newsrv->last_change = now.tv_sec;
4052 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004054 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004055 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004056 * - IP: => port=+0, relative
4057 * - IP:N => port=N, absolute
4058 * - IP:+N => port=+N, relative
4059 * - IP:-N => port=-N, relative
4060 */
4061 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004062 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063 if (rport) {
4064 *rport++ = 0;
4065 realport = atol(rport);
4066 if (!isdigit((unsigned char)*rport))
4067 newsrv->state |= SRV_MAPPORTS;
4068 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004070
Willy Tarreaufab5a432011-03-04 15:31:53 +01004071 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004072 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004073 if (!sk) {
4074 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
4078 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004079 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02004080 newsrv->sock = &sock_raw;
4081 newsrv->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004082
4083 if (!sk) {
4084 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4085 file, linenum, newsrv->addr.ss_family, args[2]);
4086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
4088 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004089 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004090
4091 newsrv->check_port = curproxy->defsrv.check_port;
4092 newsrv->inter = curproxy->defsrv.inter;
4093 newsrv->fastinter = curproxy->defsrv.fastinter;
4094 newsrv->downinter = curproxy->defsrv.downinter;
4095 newsrv->rise = curproxy->defsrv.rise;
4096 newsrv->fall = curproxy->defsrv.fall;
4097 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4098 newsrv->minconn = curproxy->defsrv.minconn;
4099 newsrv->maxconn = curproxy->defsrv.maxconn;
4100 newsrv->slowstart = curproxy->defsrv.slowstart;
4101 newsrv->onerror = curproxy->defsrv.onerror;
4102 newsrv->consecutive_errors_limit
4103 = curproxy->defsrv.consecutive_errors_limit;
4104 newsrv->uweight = newsrv->iweight
4105 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004107 newsrv->curfd = -1; /* no health-check in progress */
4108 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004109
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004110 cur_arg = 3;
4111 } else {
4112 newsrv = &curproxy->defsrv;
4113 cur_arg = 1;
4114 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004115
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004117 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004118 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004119
4120 if (!*args[cur_arg + 1]) {
4121 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4122 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004125 }
4126
4127 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004128 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004129
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004130 if (newsrv->puid <= 0) {
4131 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004132 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004135 }
4136
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004137 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4138 if (node) {
4139 struct server *target = container_of(node, struct server, conf.id);
4140 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4141 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
4144 }
4145 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004146 cur_arg += 2;
4147 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004148 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 newsrv->cookie = strdup(args[cur_arg + 1]);
4150 newsrv->cklen = strlen(args[cur_arg + 1]);
4151 cur_arg += 2;
4152 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004154 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4155 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4156 cur_arg += 2;
4157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004159 if (!*args[cur_arg + 1]) {
4160 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4161 file, linenum, args[cur_arg]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004167 if (newsrv->rise <= 0) {
4168 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4169 file, linenum, args[cur_arg]);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
4173
Willy Tarreau96839092010-03-29 10:02:24 +02004174 if (newsrv->health)
4175 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 cur_arg += 2;
4177 }
4178 else if (!strcmp(args[cur_arg], "fall")) {
4179 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004180
4181 if (!*args[cur_arg + 1]) {
4182 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4183 file, linenum, args[cur_arg]);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187
4188 if (newsrv->fall <= 0) {
4189 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4190 file, linenum, args[cur_arg]);
4191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
4193 }
4194
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 cur_arg += 2;
4196 }
4197 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004198 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4199 if (err) {
4200 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4201 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004204 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004205 if (val <= 0) {
4206 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4207 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004210 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004211 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 cur_arg += 2;
4213 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004214 else if (!strcmp(args[cur_arg], "fastinter")) {
4215 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4216 if (err) {
4217 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4218 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004221 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004222 if (val <= 0) {
4223 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4224 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004227 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004228 newsrv->fastinter = val;
4229 cur_arg += 2;
4230 }
4231 else if (!strcmp(args[cur_arg], "downinter")) {
4232 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4233 if (err) {
4234 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4235 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004238 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004239 if (val <= 0) {
4240 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4241 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004244 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004245 newsrv->downinter = val;
4246 cur_arg += 2;
4247 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004248 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004249 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004250 if (!sk) {
4251 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004256 cur_arg += 2;
4257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 else if (!strcmp(args[cur_arg], "port")) {
4259 newsrv->check_port = atol(args[cur_arg + 1]);
4260 cur_arg += 2;
4261 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004262 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 newsrv->state |= SRV_BACKUP;
4264 cur_arg ++;
4265 }
Simon Hormanfa461682011-06-25 09:39:49 +09004266 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4267 newsrv->state |= SRV_NON_STICK;
4268 cur_arg ++;
4269 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004270 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4271 newsrv->state |= SRV_SEND_PROXY;
4272 cur_arg ++;
4273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 else if (!strcmp(args[cur_arg], "weight")) {
4275 int w;
4276 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004277 if (w < 0 || w > 256) {
4278 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004283 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 cur_arg += 2;
4285 }
4286 else if (!strcmp(args[cur_arg], "minconn")) {
4287 newsrv->minconn = atol(args[cur_arg + 1]);
4288 cur_arg += 2;
4289 }
4290 else if (!strcmp(args[cur_arg], "maxconn")) {
4291 newsrv->maxconn = atol(args[cur_arg + 1]);
4292 cur_arg += 2;
4293 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004294 else if (!strcmp(args[cur_arg], "maxqueue")) {
4295 newsrv->maxqueue = atol(args[cur_arg + 1]);
4296 cur_arg += 2;
4297 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004298 else if (!strcmp(args[cur_arg], "slowstart")) {
4299 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004300 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004301 if (err) {
4302 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4303 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004306 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004307 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004308 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4309 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004312 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004313 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004314 cur_arg += 2;
4315 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004316 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004317
4318 if (!*args[cur_arg + 1]) {
4319 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4320 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004323 }
4324
4325 newsrv->trackit = strdup(args[cur_arg + 1]);
4326
4327 cur_arg += 2;
4328 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004329 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 global.maxsock++;
4331 do_check = 1;
4332 cur_arg += 1;
4333 }
Willy Tarreau96839092010-03-29 10:02:24 +02004334 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4335 newsrv->state |= SRV_MAINTAIN;
4336 newsrv->state &= ~SRV_RUNNING;
4337 newsrv->health = 0;
4338 cur_arg += 1;
4339 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004340 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004341 if (!strcmp(args[cur_arg + 1], "none"))
4342 newsrv->observe = HANA_OBS_NONE;
4343 else if (!strcmp(args[cur_arg + 1], "layer4"))
4344 newsrv->observe = HANA_OBS_LAYER4;
4345 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4346 if (curproxy->mode != PR_MODE_HTTP) {
4347 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4348 file, linenum, args[cur_arg + 1]);
4349 err_code |= ERR_ALERT;
4350 }
4351 newsrv->observe = HANA_OBS_LAYER7;
4352 }
4353 else {
4354 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004355 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004356 file, linenum, args[cur_arg], args[cur_arg + 1]);
4357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360
4361 cur_arg += 2;
4362 }
4363 else if (!strcmp(args[cur_arg], "on-error")) {
4364 if (!strcmp(args[cur_arg + 1], "fastinter"))
4365 newsrv->onerror = HANA_ONERR_FASTINTER;
4366 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4367 newsrv->onerror = HANA_ONERR_FAILCHK;
4368 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4369 newsrv->onerror = HANA_ONERR_SUDDTH;
4370 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4371 newsrv->onerror = HANA_ONERR_MARKDWN;
4372 else {
4373 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004374 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004375 file, linenum, args[cur_arg], args[cur_arg + 1]);
4376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
4378 }
4379
4380 cur_arg += 2;
4381 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004382 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4383 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4384 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4385 else {
4386 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4387 file, linenum, args[cur_arg], args[cur_arg + 1]);
4388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
4390 }
4391
4392 cur_arg += 2;
4393 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004394 else if (!strcmp(args[cur_arg], "error-limit")) {
4395 if (!*args[cur_arg + 1]) {
4396 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4397 file, linenum, args[cur_arg]);
4398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401
4402 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4403
4404 if (newsrv->consecutive_errors_limit <= 0) {
4405 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4406 file, linenum, args[cur_arg]);
4407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
4409 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004410 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004411 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004412 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004413 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004414 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004415
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004417#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004418 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004419 file, linenum, "source", "usesrc");
4420#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004421 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004423#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426 }
4427 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004428 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4429 if (!sk) {
4430 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
4434 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004435
4436 if (port_low != port_high) {
4437 int i;
4438 if (port_low <= 0 || port_low > 65535 ||
4439 port_high <= 0 || port_high > 65535 ||
4440 port_low > port_high) {
4441 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4442 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004445 }
4446 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4447 for (i = 0; i < newsrv->sport_range->size; i++)
4448 newsrv->sport_range->ports[i] = port_low + i;
4449 }
4450
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004452 while (*(args[cur_arg])) {
4453 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004454#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4455#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004456 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4457 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4458 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004461 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004462#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004463 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004464 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004465 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004468 }
4469 if (!strcmp(args[cur_arg + 1], "client")) {
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_CLI;
4472 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004473 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004474 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004475 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4476 char *name, *end;
4477
4478 name = args[cur_arg+1] + 7;
4479 while (isspace(*name))
4480 name++;
4481
4482 end = name;
4483 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4484 end++;
4485
4486 newsrv->state &= ~SRV_TPROXY_MASK;
4487 newsrv->state |= SRV_TPROXY_DYN;
4488 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4489 newsrv->bind_hdr_len = end - name;
4490 memcpy(newsrv->bind_hdr_name, name, end - name);
4491 newsrv->bind_hdr_name[end-name] = '\0';
4492 newsrv->bind_hdr_occ = -1;
4493
4494 /* now look for an occurrence number */
4495 while (isspace(*end))
4496 end++;
4497 if (*end == ',') {
4498 end++;
4499 name = end;
4500 if (*end == '-')
4501 end++;
4502 while (isdigit(*end))
4503 end++;
4504 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4505 }
4506
4507 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4508 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4509 " occurrences values smaller than %d.\n",
4510 file, linenum, MAX_HDR_HISTORY);
4511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
4513 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004514 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004515 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004516 if (!sk) {
4517 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
4520 }
4521 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004522 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004523 }
4524 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004525#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004526 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004527#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004528 cur_arg += 2;
4529 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004530#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004531 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004532 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004533 err_code |= ERR_ALERT | ERR_FATAL;
4534 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004535#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4536 } /* "usesrc" */
4537
4538 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4539#ifdef SO_BINDTODEVICE
4540 if (!*args[cur_arg + 1]) {
4541 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004545 }
4546 if (newsrv->iface_name)
4547 free(newsrv->iface_name);
4548
4549 newsrv->iface_name = strdup(args[cur_arg + 1]);
4550 newsrv->iface_len = strlen(newsrv->iface_name);
4551 global.last_checks |= LSTCHK_NETADM;
4552#else
4553 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4554 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004557#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004558 cur_arg += 2;
4559 continue;
4560 }
4561 /* this keyword in not an option of "source" */
4562 break;
4563 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004565 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004566 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4567 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004568 err_code |= ERR_ALERT | ERR_FATAL;
4569 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004572 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004573 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 +01004574 file, linenum, newsrv->id);
4575 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004576 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 +01004577 file, linenum);
4578
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 }
4582 }
4583
4584 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004585 if (newsrv->trackit) {
4586 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4587 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004590 }
4591
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004592 /* try to get the port from check_addr if check_port not set */
4593 if (!newsrv->check_port)
4594 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004595
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4597 newsrv->check_port = realport; /* by default */
4598 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004599 /* not yet valid, because no port was set on
4600 * the server either. We'll check if we have
4601 * a known port on the first listener.
4602 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004603 struct listener *l = curproxy->listen;
4604 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4605 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004606 }
4607 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4609 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004613
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004614 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004615 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004616 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4617 err_code |= ERR_ALERT | ERR_ABORT;
4618 goto out;
4619 }
4620
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004621 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 newsrv->state |= SRV_CHECKED;
4623 }
4624
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004625 if (!defsrv) {
4626 if (newsrv->state & SRV_BACKUP)
4627 curproxy->srv_bck++;
4628 else
4629 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004630
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004631 newsrv->prev_state = newsrv->state;
4632 }
William Lallemanda73203e2012-03-12 12:48:57 +01004633 }
4634
4635 else if (strcmp(args[0], "unique-id-format") == 0) {
4636 if (!*(args[1])) {
4637 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
4640 }
4641 parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
William Lallemand723b73a2012-02-08 16:37:49 +01004642 }
William Lallemanda73203e2012-03-12 12:48:57 +01004643
4644 else if (strcmp(args[0], "unique-id-header") == 0) {
4645 if (!*(args[1])) {
4646 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
4650 free(curproxy->header_unique_id);
4651 curproxy->header_unique_id = strdup(args[1]);
4652 }
4653
William Lallemand723b73a2012-02-08 16:37:49 +01004654 else if (strcmp(args[0], "log-format") == 0) {
4655 if (!*(args[1])) {
4656 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
4659 }
William Lallemand1d705562012-03-12 12:46:41 +01004660 parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 }
William Lallemand723b73a2012-02-08 16:37:49 +01004662
William Lallemand0f99e342011-10-12 17:50:54 +02004663 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4664 /* delete previous herited or defined syslog servers */
4665 struct logsrv *back;
4666
4667 if (*(args[1]) != 0) {
4668 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
4671 }
4672
William Lallemand723b73a2012-02-08 16:37:49 +01004673 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4674 LIST_DEL(&tmplogsrv->list);
4675 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004676 }
4677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004679 struct logsrv *logsrv;
4680
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004682 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004683 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004684 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004685 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004686 LIST_INIT(&node->list);
4687 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 }
4690 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004691
4692 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693
William Lallemand0f99e342011-10-12 17:50:54 +02004694 logsrv->facility = get_log_facility(args[2]);
4695 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
4699
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 }
4701
William Lallemand0f99e342011-10-12 17:50:54 +02004702 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004704 logsrv->level = get_log_level(args[3]);
4705 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004706 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 }
4711 }
4712
William Lallemand0f99e342011-10-12 17:50:54 +02004713 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004714 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004715 logsrv->minlvl = get_log_level(args[4]);
4716 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004717 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004721 }
4722 }
4723
Robert Tsai81ae1952007-12-05 10:47:29 +01004724 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004725 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004726 if (!sk) {
4727 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004728 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731 }
William Lallemand0f99e342011-10-12 17:50:54 +02004732 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004733 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004734 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004735 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004736 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
William Lallemand0f99e342011-10-12 17:50:54 +02004740 logsrv->addr = *sk;
4741 if (!get_host_port(&logsrv->addr))
4742 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
William Lallemand0f99e342011-10-12 17:50:54 +02004744
4745 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 }
4747 else {
4748 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4749 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
4753 }
4754 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004755 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004756 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004757
Willy Tarreau977b8e42006-12-29 14:19:17 +01004758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004759 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004760
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004762 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4763 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004767
4768 /* we must first clear any optional default setting */
4769 curproxy->options &= ~PR_O_TPXY_MASK;
4770 free(curproxy->iface_name);
4771 curproxy->iface_name = NULL;
4772 curproxy->iface_len = 0;
4773
Willy Tarreaud5191e72010-02-09 20:50:45 +01004774 sk = str2sa(args[1]);
4775 if (!sk) {
4776 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
4780 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004782
4783 cur_arg = 2;
4784 while (*(args[cur_arg])) {
4785 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004786#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4787#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004788 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4789 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4790 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004793 }
4794#endif
4795 if (!*args[cur_arg + 1]) {
4796 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4797 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004800 }
4801
4802 if (!strcmp(args[cur_arg + 1], "client")) {
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_CLI;
4805 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004806 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004807 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004808 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4809 char *name, *end;
4810
4811 name = args[cur_arg+1] + 7;
4812 while (isspace(*name))
4813 name++;
4814
4815 end = name;
4816 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4817 end++;
4818
4819 curproxy->options &= ~PR_O_TPXY_MASK;
4820 curproxy->options |= PR_O_TPXY_DYN;
4821 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4822 curproxy->bind_hdr_len = end - name;
4823 memcpy(curproxy->bind_hdr_name, name, end - name);
4824 curproxy->bind_hdr_name[end-name] = '\0';
4825 curproxy->bind_hdr_occ = -1;
4826
4827 /* now look for an occurrence number */
4828 while (isspace(*end))
4829 end++;
4830 if (*end == ',') {
4831 end++;
4832 name = end;
4833 if (*end == '-')
4834 end++;
4835 while (isdigit(*end))
4836 end++;
4837 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4838 }
4839
4840 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4841 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4842 " occurrences values smaller than %d.\n",
4843 file, linenum, MAX_HDR_HISTORY);
4844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
4846 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004847 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004848 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004849 if (!sk) {
4850 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004855 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004856 }
4857 global.last_checks |= LSTCHK_NETADM;
4858#if !defined(CONFIG_HAP_LINUX_TPROXY)
4859 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004860#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004861#else /* no TPROXY support */
4862 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004863 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004864 err_code |= ERR_ALERT | ERR_FATAL;
4865 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004866#endif
4867 cur_arg += 2;
4868 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004869 }
4870
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004871 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4872#ifdef SO_BINDTODEVICE
4873 if (!*args[cur_arg + 1]) {
4874 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4875 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004878 }
4879 if (curproxy->iface_name)
4880 free(curproxy->iface_name);
4881
4882 curproxy->iface_name = strdup(args[cur_arg + 1]);
4883 curproxy->iface_len = strlen(curproxy->iface_name);
4884 global.last_checks |= LSTCHK_NETADM;
4885#else
4886 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4887 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004890#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004891 cur_arg += 2;
4892 continue;
4893 }
4894 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4895 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004900 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4901 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4902 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004903 err_code |= ERR_ALERT | ERR_FATAL;
4904 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4909 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004913
4914 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004915 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004916 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 }
4920 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004922 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004923 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 }
4927 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004929 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004930 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
4934 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004936 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004937 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004938 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 }
4941 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004943 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004944 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004948 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004950 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004951 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004953 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004954 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004955 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004957 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004958 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004960 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004961 }
4962 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004964 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004965 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004966 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004967 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4972 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976
4977 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004978 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004979 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004980 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
4983 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004985 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004986 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
4990 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004992 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004993 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004994 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 }
4997 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004999 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005000 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005001 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005006 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005007 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005008 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005011 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005013 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005014 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005015 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005016 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005019 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005020
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 if (curproxy == &defproxy) {
5022 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005026 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 if (*(args[1]) == 0) {
5030 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005034
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005035 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005036 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5037 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5038 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
5042 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5043 }
5044 else if (*args[2]) {
5045 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5046 file, linenum, args[0], args[2]);
5047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
5049 }
5050
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005051 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005052 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005053 wl->s = strdup(args[1]);
5054 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005055 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 }
5057 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005058 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005064
Willy Tarreauade5ec42010-01-28 19:33:49 +01005065 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005066 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005067 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005068 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 }
5071 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005072 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005073 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005074 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005075 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 }
5078 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005079 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005080 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005081 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005082 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 }
5085 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005086 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5088 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 }
5092
Willy Tarreauade5ec42010-01-28 19:33:49 +01005093 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005094 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005095 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005096 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 }
5099 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005100 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005101 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005102 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
5106 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005108 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005109 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005110 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
5113 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005114 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005115
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 if (curproxy == &defproxy) {
5117 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005121 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005122 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 if (*(args[1]) == 0) {
5125 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
5129
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005130 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005131 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5132 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5133 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
5136 }
5137 err_code |= warnif_cond_requires_req(cond, file, linenum);
5138 }
5139 else if (*args[2]) {
5140 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5141 file, linenum, args[0], args[2]);
5142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
5144 }
5145
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005146 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005147 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005148 wl->s = strdup(args[1]);
5149 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
5151 else if (!strcmp(args[0], "errorloc") ||
5152 !strcmp(args[0], "errorloc302") ||
5153 !strcmp(args[0], "errorloc303")) { /* error location */
5154 int errnum, errlen;
5155 char *err;
5156
Willy Tarreau977b8e42006-12-29 14:19:17 +01005157 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005158 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005159
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005161 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
5165
5166 errnum = atol(args[1]);
5167 if (!strcmp(args[0], "errorloc303")) {
5168 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5169 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5170 } else {
5171 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5172 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5173 }
5174
Willy Tarreau0f772532006-12-23 20:51:41 +01005175 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5176 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005177 chunk_destroy(&curproxy->errmsg[rc]);
5178 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005179 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005182
5183 if (rc >= HTTP_ERR_SIZE) {
5184 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5185 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 free(err);
5187 }
5188 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005189 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5190 int errnum, errlen, fd;
5191 char *err;
5192 struct stat stat;
5193
5194 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005196
5197 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005198 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005201 }
5202
5203 fd = open(args[2], O_RDONLY);
5204 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5205 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5206 file, linenum, args[2], args[1]);
5207 if (fd >= 0)
5208 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005209 err_code |= ERR_ALERT | ERR_FATAL;
5210 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005211 }
5212
Willy Tarreau27a674e2009-08-17 07:23:33 +02005213 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005214 errlen = stat.st_size;
5215 } else {
5216 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005217 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005218 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005219 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005220 }
5221
5222 err = malloc(errlen); /* malloc() must succeed during parsing */
5223 errnum = read(fd, err, errlen);
5224 if (errnum != errlen) {
5225 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5226 file, linenum, args[2], args[1]);
5227 close(fd);
5228 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005231 }
5232 close(fd);
5233
5234 errnum = atol(args[1]);
5235 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5236 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005237 chunk_destroy(&curproxy->errmsg[rc]);
5238 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005239 break;
5240 }
5241 }
5242
5243 if (rc >= HTTP_ERR_SIZE) {
5244 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5245 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005246 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005247 free(err);
5248 }
5249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005251 struct cfg_kw_list *kwl;
5252 int index;
5253
5254 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5255 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5256 if (kwl->kw[index].section != CFG_LISTEN)
5257 continue;
5258 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5259 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005260 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005261 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005262 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005263 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005264 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005267 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005268 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005269 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_WARN;
5271 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005272 }
Willy Tarreau93893792009-07-23 13:19:11 +02005273 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005274 }
5275 }
5276 }
5277
Willy Tarreau6daf3432008-01-22 16:44:08 +01005278 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 }
Willy Tarreau93893792009-07-23 13:19:11 +02005282 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005283 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005284 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285}
5286
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005287int
5288cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5289{
5290
5291 int err_code = 0;
5292 const char *err;
5293
5294 if (!strcmp(args[0], "userlist")) { /* new userlist */
5295 struct userlist *newul;
5296
5297 if (!*args[1]) {
5298 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5299 file, linenum, args[0]);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 }
5303
5304 err = invalid_char(args[1]);
5305 if (err) {
5306 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5307 file, linenum, *err, args[0], args[1]);
5308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
5310 }
5311
5312 for (newul = userlist; newul; newul = newul->next)
5313 if (!strcmp(newul->name, args[1])) {
5314 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5315 file, linenum, args[1]);
5316 err_code |= ERR_WARN;
5317 goto out;
5318 }
5319
5320 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5321 if (!newul) {
5322 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5323 err_code |= ERR_ALERT | ERR_ABORT;
5324 goto out;
5325 }
5326
5327 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5328 newul->name = strdup(args[1]);
5329
5330 if (!newul->groupusers | !newul->name) {
5331 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5332 err_code |= ERR_ALERT | ERR_ABORT;
5333 goto out;
5334 }
5335
5336 newul->next = userlist;
5337 userlist = newul;
5338
5339 } else if (!strcmp(args[0], "group")) { /* new group */
5340 int cur_arg, i;
5341 const char *err;
5342
5343 if (!*args[1]) {
5344 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5345 file, linenum, args[0]);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 }
5349
5350 err = invalid_char(args[1]);
5351 if (err) {
5352 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5353 file, linenum, *err, args[0], args[1]);
5354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
5357
5358 for(i = 0; i < userlist->grpcnt; i++)
5359 if (!strcmp(userlist->groups[i], args[1])) {
5360 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5361 file, linenum, args[1], userlist->name);
5362 err_code |= ERR_ALERT;
5363 goto out;
5364 }
5365
5366 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5367 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5368 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372
5373 cur_arg = 2;
5374
5375 while (*args[cur_arg]) {
5376 if (!strcmp(args[cur_arg], "users")) {
5377 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5378 cur_arg += 2;
5379 continue;
5380 } else {
5381 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5382 file, linenum, args[0]);
5383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
5385 }
5386 }
5387
5388 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5389 } else if (!strcmp(args[0], "user")) { /* new user */
5390 struct auth_users *newuser;
5391 int cur_arg;
5392
5393 if (!*args[1]) {
5394 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5395 file, linenum, args[0]);
5396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
5399
5400 for (newuser = userlist->users; newuser; newuser = newuser->next)
5401 if (!strcmp(newuser->user, args[1])) {
5402 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5403 file, linenum, args[1], userlist->name);
5404 err_code |= ERR_ALERT;
5405 goto out;
5406 }
5407
5408 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5409 if (!newuser) {
5410 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5411 err_code |= ERR_ALERT | ERR_ABORT;
5412 goto out;
5413 }
5414
5415 newuser->user = strdup(args[1]);
5416
5417 newuser->next = userlist->users;
5418 userlist->users = newuser;
5419
5420 cur_arg = 2;
5421
5422 while (*args[cur_arg]) {
5423 if (!strcmp(args[cur_arg], "password")) {
5424#ifndef CONFIG_HAP_CRYPT
5425 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5426 file, linenum);
5427 err_code |= ERR_ALERT;
5428#endif
5429 newuser->pass = strdup(args[cur_arg + 1]);
5430 cur_arg += 2;
5431 continue;
5432 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5433 newuser->pass = strdup(args[cur_arg + 1]);
5434 newuser->flags |= AU_O_INSECURE;
5435 cur_arg += 2;
5436 continue;
5437 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005438 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005439 cur_arg += 2;
5440 continue;
5441 } else {
5442 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5443 file, linenum, args[0]);
5444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
5447 }
5448 } else {
5449 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5450 err_code |= ERR_ALERT | ERR_FATAL;
5451 }
5452
5453out:
5454 return err_code;
5455}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005456
5457/*
5458 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005459 * Returns the error code, 0 if OK, or any combination of :
5460 * - ERR_ABORT: must abort ASAP
5461 * - ERR_FATAL: we can continue parsing but not start the service
5462 * - ERR_WARN: a warning has been emitted
5463 * - ERR_ALERT: an alert has been emitted
5464 * Only the two first ones can stop processing, the two others are just
5465 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005467int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005469 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 FILE *f;
5471 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005473 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005474
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 if ((f=fopen(file,"r")) == NULL)
5476 return -1;
5477
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005478 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005479 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005480 char *end;
5481 char *args[MAX_LINE_ARGS + 1];
5482 char *line = thisline;
5483
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 linenum++;
5485
5486 end = line + strlen(line);
5487
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005488 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5489 /* Check if we reached the limit and the last char is not \n.
5490 * Watch out for the last line without the terminating '\n'!
5491 */
5492 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005493 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005494 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005495 }
5496
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005498 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 line++;
5500
5501 arg = 0;
5502 args[arg] = line;
5503
5504 while (*line && arg < MAX_LINE_ARGS) {
5505 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5506 * C equivalent value. Other combinations left unchanged (eg: \1).
5507 */
5508 if (*line == '\\') {
5509 int skip = 0;
5510 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5511 *line = line[1];
5512 skip = 1;
5513 }
5514 else if (line[1] == 'r') {
5515 *line = '\r';
5516 skip = 1;
5517 }
5518 else if (line[1] == 'n') {
5519 *line = '\n';
5520 skip = 1;
5521 }
5522 else if (line[1] == 't') {
5523 *line = '\t';
5524 skip = 1;
5525 }
5526 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005527 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528 unsigned char hex1, hex2;
5529 hex1 = toupper(line[2]) - '0';
5530 hex2 = toupper(line[3]) - '0';
5531 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5532 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5533 *line = (hex1<<4) + hex2;
5534 skip = 3;
5535 }
5536 else {
5537 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005538 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 }
5540 }
5541 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005542 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 end -= skip;
5544 }
5545 line++;
5546 }
5547 else if (*line == '#' || *line == '\n' || *line == '\r') {
5548 /* end of string, end of loop */
5549 *line = 0;
5550 break;
5551 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005552 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005554 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005555 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556 line++;
5557 args[++arg] = line;
5558 }
5559 else {
5560 line++;
5561 }
5562 }
5563
5564 /* empty line */
5565 if (!**args)
5566 continue;
5567
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005568 if (*line) {
5569 /* we had to stop due to too many args.
5570 * Let's terminate the string, print the offending part then cut the
5571 * last arg.
5572 */
5573 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5574 line++;
5575 *line = '\0';
5576
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005577 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005578 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005579 err_code |= ERR_ALERT | ERR_FATAL;
5580 args[arg] = line;
5581 }
5582
Willy Tarreau540abe42007-05-02 20:50:16 +02005583 /* zero out remaining args and ensure that at least one entry
5584 * is zeroed out.
5585 */
5586 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 args[arg] = line;
5588 }
5589
Willy Tarreau3842f002009-06-14 11:39:52 +02005590 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005591 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005592 char *tmp;
5593
Willy Tarreau3842f002009-06-14 11:39:52 +02005594 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005595 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005596 for (arg=0; *args[arg+1]; arg++)
5597 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005598 *tmp = '\0'; // fix the next arg to \0
5599 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005600 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005601 else if (!strcmp(args[0], "default")) {
5602 kwm = KWM_DEF;
5603 for (arg=0; *args[arg+1]; arg++)
5604 args[arg] = args[arg+1]; // shift args after inversion
5605 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005606
William Lallemand0f99e342011-10-12 17:50:54 +02005607 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5608 strcmp(args[0], "log") != 0) {
5609 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005611 }
5612
Willy Tarreau977b8e42006-12-29 14:19:17 +01005613 if (!strcmp(args[0], "listen") ||
5614 !strcmp(args[0], "frontend") ||
5615 !strcmp(args[0], "backend") ||
5616 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005617 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005618 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005619 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005620 cursection = strdup(args[0]);
5621 }
5622 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005624 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005625 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005626 }
5627 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005628 confsect = CFG_USERLIST;
5629 free(cursection);
5630 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005631 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005632 else if (!strcmp(args[0], "peers")) {
5633 confsect = CFG_PEERS;
5634 free(cursection);
5635 cursection = strdup(args[0]);
5636 }
5637
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 /* else it's a section keyword */
5639
5640 switch (confsect) {
5641 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005642 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 break;
5644 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005645 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005647 case CFG_USERLIST:
5648 err_code |= cfg_parse_users(file, linenum, args, kwm);
5649 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005650 case CFG_PEERS:
5651 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5652 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005654 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005655 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005657
5658 if (err_code & ERR_ABORT)
5659 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005661 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005662 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005663 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005664 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005665}
5666
Willy Tarreaubb925012009-07-23 13:36:36 +02005667/*
5668 * Returns the error code, 0 if OK, or any combination of :
5669 * - ERR_ABORT: must abort ASAP
5670 * - ERR_FATAL: we can continue parsing but not start the service
5671 * - ERR_WARN: a warning has been emitted
5672 * - ERR_ALERT: an alert has been emitted
5673 * Only the two first ones can stop processing, the two others are just
5674 * indicators.
5675 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005676int check_config_validity()
5677{
5678 int cfgerr = 0;
5679 struct proxy *curproxy = NULL;
5680 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005681 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005682 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005683 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684
5685 /*
5686 * Now, check for the integrity of all that we have collected.
5687 */
5688
5689 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005690 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005692 /* first, we will invert the proxy list order */
5693 curproxy = NULL;
5694 while (proxy) {
5695 struct proxy *next;
5696
5697 next = proxy->next;
5698 proxy->next = curproxy;
5699 curproxy = proxy;
5700 if (!next)
5701 break;
5702 proxy = next;
5703 }
5704
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005706 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005707 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005708 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005709 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005710 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005711 unsigned int next_id;
5712
5713 if (!curproxy->uuid) {
5714 /* proxy ID not set, use automatic numbering with first
5715 * spare entry starting with next_pxid.
5716 */
5717 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5718 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5719 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005720 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005721 next_pxid++;
5722
Willy Tarreau55ea7572007-06-17 19:56:27 +02005723
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005725 /* ensure we don't keep listeners uselessly bound */
5726 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 curproxy = curproxy->next;
5728 continue;
5729 }
5730
Willy Tarreauff01a212009-03-15 13:46:16 +01005731 switch (curproxy->mode) {
5732 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005733 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005734 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005735 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5736 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005737 cfgerr++;
5738 }
5739
5740 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005741 Warning("config : servers will be ignored for %s '%s'.\n",
5742 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005743 break;
5744
5745 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005746 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005747 break;
5748
5749 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005750 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005751 break;
5752 }
5753
5754 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005755 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5756 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 cfgerr++;
5758 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005759
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005760 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005761 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005762 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005763 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5764 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005765 cfgerr++;
5766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005768 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005769 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5770 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005771 cfgerr++;
5772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005774 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005775 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5776 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005777 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005778 }
5779 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005780 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005781 /* If no LB algo is set in a backend, and we're not in
5782 * transparent mode, dispatch mode nor proxy mode, we
5783 * want to use balance roundrobin by default.
5784 */
5785 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5786 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 }
5788 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005789
Willy Tarreau1620ec32011-08-06 17:05:02 +02005790 if (curproxy->options & PR_O_DISPATCH)
5791 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5792 else if (curproxy->options & PR_O_HTTP_PROXY)
5793 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5794 else if (curproxy->options & PR_O_TRANSP)
5795 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005796
Willy Tarreau1620ec32011-08-06 17:05:02 +02005797 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5798 if (curproxy->options & PR_O_DISABLE404) {
5799 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5800 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5801 err_code |= ERR_WARN;
5802 curproxy->options &= ~PR_O_DISABLE404;
5803 }
5804 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5805 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5806 "send-state", proxy_type_str(curproxy), curproxy->id);
5807 err_code |= ERR_WARN;
5808 curproxy->options &= ~PR_O2_CHK_SNDST;
5809 }
Willy Tarreauef781042010-01-27 11:53:01 +01005810 }
5811
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005812 /* if a default backend was specified, let's find it */
5813 if (curproxy->defbe.name) {
5814 struct proxy *target;
5815
Alex Williams96532db2009-11-01 21:27:13 -05005816 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005817 if (!target) {
5818 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5819 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005820 cfgerr++;
5821 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005822 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5823 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005824 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005825 } else {
5826 free(curproxy->defbe.name);
5827 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005828 /* we force the backend to be present on at least all of
5829 * the frontend's processes.
5830 */
5831 target->bind_proc = curproxy->bind_proc ?
5832 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005833
5834 /* Emit a warning if this proxy also has some servers */
5835 if (curproxy->srv) {
5836 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5837 curproxy->id);
5838 err_code |= ERR_WARN;
5839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 }
5841 }
5842
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005843 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005844 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5845 /* map jump target for ACT_SETBE in req_rep chain */
5846 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005847 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005848 struct proxy *target;
5849
Willy Tarreaua496b602006-12-17 23:15:24 +01005850 if (exp->action != ACT_SETBE)
5851 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005852
Alex Williams96532db2009-11-01 21:27:13 -05005853 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005854 if (!target) {
5855 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5856 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005857 cfgerr++;
5858 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005859 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5860 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005861 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005862 } else {
5863 free((void *)exp->replace);
5864 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005865 /* we force the backend to be present on at least all of
5866 * the frontend's processes.
5867 */
5868 target->bind_proc = curproxy->bind_proc ?
5869 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005870 }
5871 }
5872 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005873
5874 /* find the target proxy for 'use_backend' rules */
5875 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005876 struct proxy *target;
5877
Alex Williams96532db2009-11-01 21:27:13 -05005878 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005879
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005880 if (!target) {
5881 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5882 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005883 cfgerr++;
5884 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005885 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5886 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005887 cfgerr++;
5888 } else {
5889 free((void *)rule->be.name);
5890 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005891 /* we force the backend to be present on at least all of
5892 * the frontend's processes.
5893 */
5894 target->bind_proc = curproxy->bind_proc ?
5895 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005896 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005897 }
5898
5899 /* find the target proxy for 'use_backend' rules */
5900 list_for_each_entry(srule, &curproxy->server_rules, list) {
5901 struct server *target = findserver(curproxy, srule->srv.name);
5902
5903 if (!target) {
5904 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5905 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5906 cfgerr++;
5907 continue;
5908 }
5909 free((void *)srule->srv.name);
5910 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005911 }
5912
Emeric Brunb982a3d2010-01-04 15:45:53 +01005913 /* find the target table for 'stick' rules */
5914 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5915 struct proxy *target;
5916
Emeric Brun1d33b292010-01-04 15:47:17 +01005917 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5918 if (mrule->flags & STK_IS_STORE)
5919 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5920
Emeric Brunb982a3d2010-01-04 15:45:53 +01005921 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005922 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005923 else
5924 target = curproxy;
5925
5926 if (!target) {
5927 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5928 curproxy->id, mrule->table.name);
5929 cfgerr++;
5930 }
5931 else if (target->table.size == 0) {
5932 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5933 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5934 cfgerr++;
5935 }
Willy Tarreau12785782012-04-27 21:37:17 +02005936 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5937 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005938 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5939 cfgerr++;
5940 }
5941 else {
5942 free((void *)mrule->table.name);
5943 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005944 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005945 }
5946 }
5947
5948 /* find the target table for 'store response' rules */
5949 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5950 struct proxy *target;
5951
Emeric Brun1d33b292010-01-04 15:47:17 +01005952 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5953
Emeric Brunb982a3d2010-01-04 15:45:53 +01005954 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005955 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005956 else
5957 target = curproxy;
5958
5959 if (!target) {
5960 Alert("Proxy '%s': unable to find store table '%s'.\n",
5961 curproxy->id, mrule->table.name);
5962 cfgerr++;
5963 }
5964 else if (target->table.size == 0) {
5965 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5966 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5967 cfgerr++;
5968 }
Willy Tarreau12785782012-04-27 21:37:17 +02005969 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5970 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005971 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5972 cfgerr++;
5973 }
5974 else {
5975 free((void *)mrule->table.name);
5976 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005977 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005978 }
5979 }
5980
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005981 /* find the target table for 'tcp-request' layer 4 rules */
5982 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5983 struct proxy *target;
5984
Willy Tarreau56123282010-08-06 19:06:56 +02005985 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005986 continue;
5987
5988 if (trule->act_prm.trk_ctr.table.n)
5989 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5990 else
5991 target = curproxy;
5992
5993 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005994 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5995 curproxy->id, trule->act_prm.trk_ctr.table.n,
5996 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005997 cfgerr++;
5998 }
5999 else if (target->table.size == 0) {
6000 Alert("Proxy '%s': table '%s' used but not configured.\n",
6001 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6002 cfgerr++;
6003 }
6004 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006005 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 +02006006 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6007 cfgerr++;
6008 }
6009 else {
6010 free(trule->act_prm.trk_ctr.table.n);
6011 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006012 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006013 * to pass a list of counters to track and allocate them right here using
6014 * stktable_alloc_data_type().
6015 */
6016 }
6017 }
6018
Willy Tarreaud1f96522010-08-03 19:34:32 +02006019 /* find the target table for 'tcp-request' layer 6 rules */
6020 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6021 struct proxy *target;
6022
Willy Tarreau56123282010-08-06 19:06:56 +02006023 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006024 continue;
6025
6026 if (trule->act_prm.trk_ctr.table.n)
6027 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6028 else
6029 target = curproxy;
6030
6031 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006032 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6033 curproxy->id, trule->act_prm.trk_ctr.table.n,
6034 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006035 cfgerr++;
6036 }
6037 else if (target->table.size == 0) {
6038 Alert("Proxy '%s': table '%s' used but not configured.\n",
6039 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6040 cfgerr++;
6041 }
6042 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006043 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 +02006044 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6045 cfgerr++;
6046 }
6047 else {
6048 free(trule->act_prm.trk_ctr.table.n);
6049 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006050 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006051 * to pass a list of counters to track and allocate them right here using
6052 * stktable_alloc_data_type().
6053 */
6054 }
6055 }
6056
Emeric Brun32da3c42010-09-23 18:39:19 +02006057 if (curproxy->table.peers.name) {
6058 struct peers *curpeers = peers;
6059
6060 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6061 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6062 free((void *)curproxy->table.peers.name);
6063 curproxy->table.peers.p = peers;
6064 break;
6065 }
6066 }
6067
6068 if (!curpeers) {
6069 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6070 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006071 free((void *)curproxy->table.peers.name);
6072 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006073 cfgerr++;
6074 }
6075 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006076 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6077 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006078 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006079 cfgerr++;
6080 }
6081 }
6082
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006083 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006084 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006085 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6086 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6087 "proxy", curproxy->id);
6088 cfgerr++;
6089 goto out_uri_auth_compat;
6090 }
6091
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006092 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006093 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006094 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006095 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006096
Willy Tarreau95fa4692010-02-01 13:05:50 +01006097 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6098 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006099
6100 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006101 uri_auth_compat_req[i++] = "realm";
6102 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6103 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006104
Willy Tarreau95fa4692010-02-01 13:05:50 +01006105 uri_auth_compat_req[i++] = "unless";
6106 uri_auth_compat_req[i++] = "{";
6107 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6108 uri_auth_compat_req[i++] = "}";
6109 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006110
Willy Tarreauff011f22011-01-06 17:51:27 +01006111 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6112 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006113 cfgerr++;
6114 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006115 }
6116
Willy Tarreauff011f22011-01-06 17:51:27 +01006117 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006118
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006119 if (curproxy->uri_auth->auth_realm) {
6120 free(curproxy->uri_auth->auth_realm);
6121 curproxy->uri_auth->auth_realm = NULL;
6122 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006123
6124 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006125 }
6126out_uri_auth_compat:
6127
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006128 cfgerr += acl_find_targets(curproxy);
6129
Willy Tarreau2738a142006-07-08 17:28:09 +02006130 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006131 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006132 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006133 (!curproxy->timeout.connect ||
6134 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006135 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006136 " | While not properly invalid, you will certainly encounter various problems\n"
6137 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006138 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006139 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006140 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006141 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006142
Willy Tarreau1fa31262007-12-03 00:36:16 +01006143 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6144 * We must still support older configurations, so let's find out whether those
6145 * parameters have been set or must be copied from contimeouts.
6146 */
6147 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006148 if (!curproxy->timeout.tarpit ||
6149 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006150 /* tarpit timeout not set. We search in the following order:
6151 * default.tarpit, curr.connect, default.connect.
6152 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006153 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006154 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006155 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006156 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006157 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006158 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006159 }
6160 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006161 (!curproxy->timeout.queue ||
6162 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006163 /* queue timeout not set. We search in the following order:
6164 * default.queue, curr.connect, default.connect.
6165 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006166 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006167 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006168 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006169 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006170 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006171 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006172 }
6173 }
6174
Willy Tarreau1620ec32011-08-06 17:05:02 +02006175 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006176 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6177 curproxy->check_req = (char *)malloc(curproxy->check_len);
6178 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006179 }
6180
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006181 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006182 if (curproxy->nb_req_cap) {
6183 if (curproxy->mode == PR_MODE_HTTP) {
6184 curproxy->req_cap_pool = create_pool("ptrcap",
6185 curproxy->nb_req_cap * sizeof(char *),
6186 MEM_F_SHARED);
6187 } else {
6188 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6189 proxy_type_str(curproxy), curproxy->id);
6190 err_code |= ERR_WARN;
6191 curproxy->to_log &= ~LW_REQHDR;
6192 curproxy->nb_req_cap = 0;
6193 }
6194 }
6195
6196 if (curproxy->nb_rsp_cap) {
6197 if (curproxy->mode == PR_MODE_HTTP) {
6198 curproxy->rsp_cap_pool = create_pool("ptrcap",
6199 curproxy->nb_rsp_cap * sizeof(char *),
6200 MEM_F_SHARED);
6201 } else {
6202 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6203 proxy_type_str(curproxy), curproxy->id);
6204 err_code |= ERR_WARN;
6205 curproxy->to_log &= ~LW_REQHDR;
6206 curproxy->nb_rsp_cap = 0;
6207 }
6208 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006209
Willy Tarreaubaaee002006-06-26 02:48:02 +02006210 /* first, we will invert the servers list order */
6211 newsrv = NULL;
6212 while (curproxy->srv) {
6213 struct server *next;
6214
6215 next = curproxy->srv->next;
6216 curproxy->srv->next = newsrv;
6217 newsrv = curproxy->srv;
6218 if (!next)
6219 break;
6220 curproxy->srv = next;
6221 }
6222
Willy Tarreaudd701652010-05-25 23:03:02 +02006223 /* assign automatic UIDs to servers which don't have one yet */
6224 next_id = 1;
6225 newsrv = curproxy->srv;
6226 while (newsrv != NULL) {
6227 if (!newsrv->puid) {
6228 /* server ID not set, use automatic numbering with first
6229 * spare entry starting with next_svid.
6230 */
6231 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6232 newsrv->conf.id.key = newsrv->puid = next_id;
6233 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6234 }
6235 next_id++;
6236 newsrv = newsrv->next;
6237 }
6238
Willy Tarreau20697042007-11-15 23:26:18 +01006239 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006240 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006241
Willy Tarreau62c3be22012-01-20 13:12:32 +01006242 /*
6243 * If this server supports a maxconn parameter, it needs a dedicated
6244 * tasks to fill the emptied slots when a connection leaves.
6245 * Also, resolve deferred tracking dependency if needed.
6246 */
6247 newsrv = curproxy->srv;
6248 while (newsrv != NULL) {
6249 if (newsrv->minconn > newsrv->maxconn) {
6250 /* Only 'minconn' was specified, or it was higher than or equal
6251 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6252 * this will avoid further useless expensive computations.
6253 */
6254 newsrv->maxconn = newsrv->minconn;
6255 } else if (newsrv->maxconn && !newsrv->minconn) {
6256 /* minconn was not specified, so we set it to maxconn */
6257 newsrv->minconn = newsrv->maxconn;
6258 }
6259
6260 if (newsrv->trackit) {
6261 struct proxy *px;
6262 struct server *srv;
6263 char *pname, *sname;
6264
6265 pname = newsrv->trackit;
6266 sname = strrchr(pname, '/');
6267
6268 if (sname)
6269 *sname++ = '\0';
6270 else {
6271 sname = pname;
6272 pname = NULL;
6273 }
6274
6275 if (pname) {
6276 px = findproxy(pname, PR_CAP_BE);
6277 if (!px) {
6278 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6279 proxy_type_str(curproxy), curproxy->id,
6280 newsrv->id, pname);
6281 cfgerr++;
6282 goto next_srv;
6283 }
6284 } else
6285 px = curproxy;
6286
6287 srv = findserver(px, sname);
6288 if (!srv) {
6289 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6290 proxy_type_str(curproxy), curproxy->id,
6291 newsrv->id, sname);
6292 cfgerr++;
6293 goto next_srv;
6294 }
6295
6296 if (!(srv->state & SRV_CHECKED)) {
6297 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6298 "tracking as it does not have checks enabled.\n",
6299 proxy_type_str(curproxy), curproxy->id,
6300 newsrv->id, px->id, srv->id);
6301 cfgerr++;
6302 goto next_srv;
6303 }
6304
6305 if (curproxy != px &&
6306 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6307 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6308 "tracking: disable-on-404 option inconsistency.\n",
6309 proxy_type_str(curproxy), curproxy->id,
6310 newsrv->id, px->id, srv->id);
6311 cfgerr++;
6312 goto next_srv;
6313 }
6314
6315 /* if the other server is forced disabled, we have to do the same here */
6316 if (srv->state & SRV_MAINTAIN) {
6317 newsrv->state |= SRV_MAINTAIN;
6318 newsrv->state &= ~SRV_RUNNING;
6319 newsrv->health = 0;
6320 }
6321
6322 newsrv->track = srv;
6323 newsrv->tracknext = srv->tracknext;
6324 srv->tracknext = newsrv;
6325
6326 free(newsrv->trackit);
6327 newsrv->trackit = NULL;
6328 }
6329 next_srv:
6330 newsrv = newsrv->next;
6331 }
6332
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006333 /* We have to initialize the server lookup mechanism depending
6334 * on what LB algorithm was choosen.
6335 */
6336
6337 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6338 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6339 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006340 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6341 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6342 init_server_map(curproxy);
6343 } else {
6344 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6345 fwrr_init_server_groups(curproxy);
6346 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006347 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006348
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006349 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006350 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6351 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6352 fwlc_init_server_tree(curproxy);
6353 } else {
6354 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6355 fas_init_server_tree(curproxy);
6356 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006357 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006358
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006359 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006360 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6361 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6362 chash_init_server_tree(curproxy);
6363 } else {
6364 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6365 init_server_map(curproxy);
6366 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006367 break;
6368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369
6370 if (curproxy->options & PR_O_LOGASAP)
6371 curproxy->to_log &= ~LW_BYTES;
6372
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006373 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006374 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006375 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6376 proxy_type_str(curproxy), curproxy->id);
6377 err_code |= ERR_WARN;
6378 }
6379
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006380 if (curproxy->mode != PR_MODE_HTTP) {
6381 int optnum;
6382
6383 if (curproxy->options & PR_O_COOK_ANY) {
6384 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6385 proxy_type_str(curproxy), curproxy->id);
6386 err_code |= ERR_WARN;
6387 }
6388
6389 if (curproxy->uri_auth) {
6390 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6391 proxy_type_str(curproxy), curproxy->id);
6392 err_code |= ERR_WARN;
6393 curproxy->uri_auth = NULL;
6394 }
6395
Willy Tarreau87cf5142011-08-19 22:57:24 +02006396 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006397 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6398 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6399 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006400 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006401 }
6402
6403 if (curproxy->options & PR_O_ORGTO) {
6404 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6405 "originalto", proxy_type_str(curproxy), curproxy->id);
6406 err_code |= ERR_WARN;
6407 curproxy->options &= ~PR_O_ORGTO;
6408 }
6409
6410 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6411 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6412 (curproxy->cap & cfg_opts[optnum].cap) &&
6413 (curproxy->options & cfg_opts[optnum].val)) {
6414 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6415 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6416 err_code |= ERR_WARN;
6417 curproxy->options &= ~cfg_opts[optnum].val;
6418 }
6419 }
6420
6421 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6422 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6423 (curproxy->cap & cfg_opts2[optnum].cap) &&
6424 (curproxy->options2 & cfg_opts2[optnum].val)) {
6425 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6426 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6427 err_code |= ERR_WARN;
6428 curproxy->options2 &= ~cfg_opts2[optnum].val;
6429 }
6430 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006431
Willy Tarreauefa5f512010-03-30 20:13:29 +02006432#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006433 if (curproxy->bind_hdr_occ) {
6434 curproxy->bind_hdr_occ = 0;
6435 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6436 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6437 err_code |= ERR_WARN;
6438 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006439#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006440 }
6441
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006443 * ensure that we're not cross-dressing a TCP server into HTTP.
6444 */
6445 newsrv = curproxy->srv;
6446 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006447 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006448 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6449 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006450 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006451 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006452
Willy Tarreau0cec3312011-10-31 13:49:26 +01006453 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6454 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6455 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6456 err_code |= ERR_WARN;
6457 }
6458
Willy Tarreauefa5f512010-03-30 20:13:29 +02006459#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006460 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6461 newsrv->bind_hdr_occ = 0;
6462 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6463 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6464 err_code |= ERR_WARN;
6465 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006466#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006467 newsrv = newsrv->next;
6468 }
6469
Willy Tarreauc1a21672009-08-16 22:37:44 +02006470 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006471 curproxy->accept = frontend_accept;
6472
Willy Tarreauc1a21672009-08-16 22:37:44 +02006473 if (curproxy->tcp_req.inspect_delay ||
6474 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006475 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006476
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006477 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006478 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006479 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006480 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006481
6482 /* both TCP and HTTP must check switching rules */
6483 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6484 }
6485
6486 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006487 if (curproxy->tcp_req.inspect_delay ||
6488 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6489 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6490
Emeric Brun97679e72010-09-23 17:56:44 +02006491 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6492 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6493
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006494 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006495 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006496 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006497 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006498
6499 /* If the backend does requires RDP cookie persistence, we have to
6500 * enable the corresponding analyser.
6501 */
6502 if (curproxy->options2 & PR_O2_RDPC_PRST)
6503 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6504 }
6505
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006506 listener = NULL;
6507 while (curproxy->listen) {
6508 struct listener *next;
6509
6510 next = curproxy->listen->next;
6511 curproxy->listen->next = listener;
6512 listener = curproxy->listen;
6513
6514 if (!next)
6515 break;
6516
6517 curproxy->listen = next;
6518 }
6519
Willy Tarreaue6b98942007-10-29 01:09:36 +01006520 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006521 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006522 listener = curproxy->listen;
6523 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006524 if (!listener->luid) {
6525 /* listener ID not set, use automatic numbering with first
6526 * spare entry starting with next_luid.
6527 */
6528 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6529 listener->conf.id.key = listener->luid = next_id;
6530 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006531 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006532 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006533
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006534 /* enable separate counters */
6535 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6536 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6537 if (!listener->name) {
6538 sprintf(trash, "sock-%d", listener->luid);
6539 listener->name = strdup(trash);
6540 }
6541 }
6542
Willy Tarreaue6b98942007-10-29 01:09:36 +01006543 if (curproxy->options & PR_O_TCP_NOLING)
6544 listener->options |= LI_O_NOLINGER;
6545 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006546 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006547 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006548 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006549 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006550 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006551 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006552
Willy Tarreau8a956912010-10-15 14:27:08 +02006553 if (listener->options & LI_O_ACC_PROXY)
6554 listener->analysers |= AN_REQ_DECODE_PROXY;
6555
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006556 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6557 listener->options |= LI_O_TCP_RULES;
6558
Willy Tarreaude3041d2010-05-31 10:56:17 +02006559 if (curproxy->mon_mask.s_addr)
6560 listener->options |= LI_O_CHK_MONNET;
6561
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006562 /* smart accept mode is automatic in HTTP mode */
6563 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6564 (curproxy->mode == PR_MODE_HTTP &&
6565 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6566 listener->options |= LI_O_NOQUICKACK;
6567
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006568 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006569 listener = listener->next;
6570 }
6571
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006572 /* Check multi-process mode compatibility for the current proxy */
6573 if (global.nbproc > 1) {
6574 int nbproc = 0;
6575 if (curproxy->bind_proc) {
6576 int proc;
6577 for (proc = 0; proc < global.nbproc; proc++) {
6578 if (curproxy->bind_proc & (1 << proc)) {
6579 nbproc++;
6580 }
6581 }
6582 } else {
6583 nbproc = global.nbproc;
6584 }
6585 if (curproxy->table.peers.name) {
6586 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6587 curproxy->id);
6588 cfgerr++;
6589 }
6590 if (nbproc > 1) {
6591 if (curproxy->uri_auth) {
6592 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6593 curproxy->id);
6594 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6595 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6596 curproxy->id);
6597 }
6598 }
6599 if (curproxy->appsession_name) {
6600 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6601 curproxy->id);
6602 }
6603 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6604 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6605 curproxy->id);
6606 }
6607 }
6608 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006609
6610 /* create the task associated with the proxy */
6611 curproxy->task = task_new();
6612 if (curproxy->task) {
6613 curproxy->task->context = curproxy;
6614 curproxy->task->process = manage_proxy;
6615 /* no need to queue, it will be done automatically if some
6616 * listener gets limited.
6617 */
6618 curproxy->task->expire = TICK_ETERNITY;
6619 } else {
6620 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6621 curproxy->id);
6622 cfgerr++;
6623 }
6624
Willy Tarreaubaaee002006-06-26 02:48:02 +02006625 curproxy = curproxy->next;
6626 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006627
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006628 /* Check multi-process mode compatibility */
6629 if (global.nbproc > 1) {
6630 if (global.stats_fe) {
6631 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6632 }
6633 }
6634
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006635 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6636 struct auth_users *curuser;
6637 int g;
6638
6639 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6640 unsigned int group_mask = 0;
6641 char *group = NULL;
6642
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006643 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006644 continue;
6645
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006646 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006647
6648 for (g = 0; g < curuserlist->grpcnt; g++)
6649 if (!strcmp(curuserlist->groups[g], group))
6650 break;
6651
6652 if (g == curuserlist->grpcnt) {
6653 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6654 curuserlist->name, group, curuser->user);
6655 err_code |= ERR_ALERT | ERR_FATAL;
6656 goto out;
6657 }
6658
6659 group_mask |= (1 << g);
6660 }
6661
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006662 free(curuser->u.groups);
6663 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006664 }
6665
6666 for (g = 0; g < curuserlist->grpcnt; g++) {
6667 char *user = NULL;
6668
6669 if (!curuserlist->groupusers[g])
6670 continue;
6671
6672 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6673 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6674 if (!strcmp(curuser->user, user))
6675 break;
6676
6677 if (!curuser) {
6678 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6679 curuserlist->name, user, curuserlist->groups[g]);
6680 err_code |= ERR_ALERT | ERR_FATAL;
6681 goto out;
6682 }
6683
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006684 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006685 }
6686
6687 free(curuserlist->groupusers[g]);
6688 }
6689
6690 free(curuserlist->groupusers);
6691
6692#ifdef DEBUG_AUTH
6693 for (g = 0; g < curuserlist->grpcnt; g++) {
6694 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6695
6696 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006697 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006698 fprintf(stderr, " %s", curuser->user);
6699 }
6700
6701 fprintf(stderr, "\n");
6702 }
6703#endif
6704
Willy Tarreaufbb78422011-06-05 15:38:35 +02006705 }
6706
6707 /* automatically compute fullconn if not set. We must not do it in the
6708 * loop above because cross-references are not yet fully resolved.
6709 */
6710 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6711 /* If <fullconn> is not set, let's set it to 10% of the sum of
6712 * the possible incoming frontend's maxconns.
6713 */
6714 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6715 struct proxy *fe;
6716 int total = 0;
6717
6718 /* sum up the number of maxconns of frontends which
6719 * reference this backend at least once or which are
6720 * the same one ('listen').
6721 */
6722 for (fe = proxy; fe; fe = fe->next) {
6723 struct switching_rule *rule;
6724 struct hdr_exp *exp;
6725 int found = 0;
6726
6727 if (!(fe->cap & PR_CAP_FE))
6728 continue;
6729
6730 if (fe == curproxy) /* we're on a "listen" instance */
6731 found = 1;
6732
6733 if (fe->defbe.be == curproxy) /* "default_backend" */
6734 found = 1;
6735
6736 /* check if a "use_backend" rule matches */
6737 if (!found) {
6738 list_for_each_entry(rule, &fe->switching_rules, list) {
6739 if (rule->be.backend == curproxy) {
6740 found = 1;
6741 break;
6742 }
6743 }
6744 }
6745
6746 /* check if a "reqsetbe" rule matches */
6747 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6748 if (exp->action == ACT_SETBE &&
6749 (struct proxy *)exp->replace == curproxy) {
6750 found = 1;
6751 break;
6752 }
6753 }
6754
6755 /* now we've checked all possible ways to reference a backend
6756 * from a frontend.
6757 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006758 if (!found)
6759 continue;
6760 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006761 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006762 /* we have the sum of the maxconns in <total>. We only
6763 * keep 10% of that sum to set the default fullconn, with
6764 * a hard minimum of 1 (to avoid a divide by zero).
6765 */
6766 curproxy->fullconn = (total + 9) / 10;
6767 if (!curproxy->fullconn)
6768 curproxy->fullconn = 1;
6769 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006770 }
6771
Willy Tarreau056f5682010-06-06 15:51:11 +02006772 /* initialize stick-tables on backend capable proxies. This must not
6773 * be done earlier because the data size may be discovered while parsing
6774 * other proxies.
6775 */
6776 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006777 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006778
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006779 /*
6780 * Recount currently required checks.
6781 */
6782
6783 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6784 int optnum;
6785
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006786 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6787 if (curproxy->options & cfg_opts[optnum].val)
6788 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006789
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006790 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6791 if (curproxy->options2 & cfg_opts2[optnum].val)
6792 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006793 }
6794
Willy Tarreau122541c2011-09-07 21:24:49 +02006795 if (peers) {
6796 struct peers *curpeers = peers, **last;
6797 struct peer *p, *pb;
6798
6799 /* Remove all peers sections which don't have a valid listener.
6800 * This can happen when a peers section is never referenced and
6801 * does not contain a local peer.
6802 */
6803 last = &peers;
6804 while (*last) {
6805 curpeers = *last;
6806 if (curpeers->peers_fe) {
6807 last = &curpeers->next;
6808 continue;
6809 }
6810
6811 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6812 curpeers->id, localpeer);
6813
6814 p = curpeers->remote;
6815 while (p) {
6816 pb = p->next;
6817 free(p->id);
6818 free(p);
6819 p = pb;
6820 }
6821
6822 /* Destroy and unlink this curpeers section.
6823 * Note: curpeers is backed up into *last.
6824 */
6825 free(curpeers->id);
6826 curpeers = curpeers->next;
6827 free(*last);
6828 *last = curpeers;
6829 }
6830 }
6831
Willy Tarreauac1932d2011-10-24 19:14:41 +02006832 if (!global.tune.max_http_hdr)
6833 global.tune.max_http_hdr = MAX_HTTP_HDR;
6834
Willy Tarreau34eb6712011-10-24 18:15:04 +02006835 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006836 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006837 MEM_F_SHARED);
6838
Willy Tarreaubb925012009-07-23 13:36:36 +02006839 if (cfgerr > 0)
6840 err_code |= ERR_ALERT | ERR_FATAL;
6841 out:
6842 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006843}
6844
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006845/*
6846 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6847 * parsing sessions.
6848 */
6849void cfg_register_keywords(struct cfg_kw_list *kwl)
6850{
6851 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6852}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006853
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006854/*
6855 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6856 */
6857void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6858{
6859 LIST_DEL(&kwl->list);
6860 LIST_INIT(&kwl->list);
6861}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006862
6863/*
6864 * Local variables:
6865 * c-indent-level: 8
6866 * c-basic-offset: 8
6867 * End:
6868 */