blob: 5f8cb9675fa259eee3ca8e4952006c920e028e1b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010049#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020050#include <proto/lb_fwlc.h>
51#include <proto/lb_fwrr.h>
52#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreaud02394b2012-05-11 18:32:18 +020064#include <proto/sock_raw.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010066#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
68
Willy Tarreauf3c69202006-07-09 16:42:34 +020069/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
70 * ssl-hello-chk option to ensure that the remote server speaks SSL.
71 *
72 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
73 */
74const char sslv3_client_hello_pkt[] = {
75 "\x16" /* ContentType : 0x16 = Hanshake */
76 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
77 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
78 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
79 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
80 "\x03\x00" /* Hello Version : 0x0300 = v3 */
81 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
82 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
83 "\x00" /* Session ID length : empty (no session ID) */
84 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
85 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
86 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
87 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
88 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
89 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
90 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
91 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
92 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
93 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
94 "\x00\x38" "\x00\x39" "\x00\x3A"
95 "\x01" /* Compression Length : 0x01 = 1 byte for types */
96 "\x00" /* Compression Type : 0x00 = NULL compression */
97};
98
Willy Tarreau3842f002009-06-14 11:39:52 +020099/* various keyword modifiers */
100enum kw_mod {
101 KWM_STD = 0, /* normal */
102 KWM_NO, /* "no" prefixed before the keyword */
103 KWM_DEF, /* "default" prefixed before the keyword */
104};
105
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100107struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100108 const char *name;
109 unsigned int val;
110 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100112 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100113};
114
115/* proxy->options */
116static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100117{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100118 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
119 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
120 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
122 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
123 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
124 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
128 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
130 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
131 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
132 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
133 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100134#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100135 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100136#else
137 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100138#endif
139
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141};
142
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143/* proxy->options2 */
144static const struct cfg_opt cfg_opts2[] =
145{
146#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
148 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
149 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100150#else
151 { "splice-request", 0, 0, 0, 0 },
152 { "splice-response", 0, 0, 0, 0 },
153 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100154#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
156 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
157 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
158 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
159 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
160 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
161 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
162 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
163 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200165 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200166 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100167 { NULL, 0, 0, 0 }
168};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169
Willy Tarreau6daf3432008-01-22 16:44:08 +0100170static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
172int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100173int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200175/* List head of all known configuration keywords */
176static struct cfg_kw_list cfg_keywords = {
177 .list = LIST_HEAD_INIT(cfg_keywords.list)
178};
179
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180/*
181 * converts <str> to a list of listeners which are dynamically allocated.
182 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
183 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
184 * - <port> is a numerical port from 1 to 65535 ;
185 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
186 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200187 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190{
191 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100192 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200193 int port, end;
194
195 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197 while (next && *next) {
198 struct sockaddr_storage ss;
199
200 str = next;
201 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100202 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 *next++ = 0;
204 }
205
Emeric Bruned760922010-10-22 17:59:25 +0200206 if (*str == '/') {
207 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
208 /* so compute max path */
209 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
210 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Emeric Bruned760922010-10-22 17:59:25 +0200212 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100213 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
214 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200215 goto fail;
216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200219 ss.ss_family = AF_UNIX;
220 if (global.unix_bind.prefix) {
221 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
222 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 }
Emeric Bruned760922010-10-22 17:59:25 +0200224 else {
225 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
226 }
227 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 }
229 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100232 ss2 = str2sa_range(str, &port, &end);
233 if (!ss2) {
234 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
235 file, line, str);
236 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 if (!port) {
240 Alert("parsing [%s:%d] : missing port number: '%s'\n",
241 file, line, str);
242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 /* OK the address looks correct */
246 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Emeric Bruned760922010-10-22 17:59:25 +0200248 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
250 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200251 goto fail;
252 }
253
254 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
256 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259 }
260
261 for (; port <= end; port++) {
262 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200263 l->next = curproxy->listen;
264 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265
266 l->fd = -1;
267 l->addr = ss;
Emeric Brund88fd822012-05-18 18:30:29 +0200268 l->sock = &sock_raw;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 l->state = LI_INIT;
270
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100271 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100273 tcpv4_add_listener(l);
274 }
Emeric Bruned760922010-10-22 17:59:25 +0200275 else if (ss.ss_family == AF_INET6) {
276 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
277 tcpv6_add_listener(l);
278 }
279 else {
280 l->perm.ux.gid = l->perm.ux.uid = -1;
281 l->perm.ux.mode = 0;
282 uxst_add_listener(l);
283 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200284
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200285 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100286 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 } /* end for(port) */
288 } /* end while(next) */
289 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291 fail:
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294}
295
Willy Tarreau977b8e42006-12-29 14:19:17 +0100296/*
297 * Sends a warning if proxy <proxy> does not have at least one of the
298 * capabilities in <cap>. An optionnal <hint> may be added at the end
299 * of the warning to help the user. Returns 1 if a warning was emitted
300 * or 0 if the condition is valid.
301 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100302int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303{
304 char *msg;
305
306 switch (cap) {
307 case PR_CAP_BE: msg = "no backend"; break;
308 case PR_CAP_FE: msg = "no frontend"; break;
309 case PR_CAP_RS: msg = "no ruleset"; break;
310 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
311 default: msg = "not enough"; break;
312 }
313
314 if (!(proxy->cap & cap)) {
315 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100316 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100317 return 1;
318 }
319 return 0;
320}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321
Willy Tarreau61d18892009-03-31 10:49:21 +0200322/* Report a warning if a rule is placed after a 'block' rule.
323 * Return 1 if the warning has been emitted, otherwise 0.
324 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100325int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200326{
327 if (!LIST_ISEMPTY(&proxy->block_cond)) {
328 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
329 file, line, arg);
330 return 1;
331 }
332 return 0;
333}
334
335/* Report a warning if a rule is placed after a reqrewrite rule.
336 * Return 1 if the warning has been emitted, otherwise 0.
337 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100338int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200339{
340 if (proxy->req_exp) {
341 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
342 file, line, arg);
343 return 1;
344 }
345 return 0;
346}
347
348/* Report a warning if a rule is placed after a reqadd rule.
349 * Return 1 if the warning has been emitted, otherwise 0.
350 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100351int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200352{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100353 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200354 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
355 file, line, arg);
356 return 1;
357 }
358 return 0;
359}
360
361/* Report a warning if a rule is placed after a redirect rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100364int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200365{
366 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
374/* Report a warning if a rule is placed after a 'use_backend' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
379 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
387/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
391 warnif_rule_after_reqadd(proxy, file, line, arg) ||
392 warnif_rule_after_redirect(proxy, file, line, arg) ||
393 warnif_rule_after_use_backend(proxy, file, line, arg);
394}
395
396/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100397int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200398{
399 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
400 warnif_rule_after_redirect(proxy, file, line, arg) ||
401 warnif_rule_after_use_backend(proxy, file, line, arg);
402}
403
404/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100405int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200406{
407 return warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100411/* Report it if a request ACL condition uses some response-only parameters. It
412 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
413 * Note that <cond> may be NULL and then will be ignored.
414 */
415static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
416{
417 struct acl *acl;
418
419 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
420 return 0;
421
422 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
423 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
424 file, line, acl ? acl->name : "(unknown)");
425 return ERR_WARN;
426}
427
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100428/* Report it if a request ACL condition uses some request-only volatile parameters.
429 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
430 * Note that <cond> may be NULL and then will be ignored.
431 */
432static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
433{
434 struct acl *acl;
435
436 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
437 return 0;
438
439 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
440 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
441 file, line, acl ? acl->name : "(unknown)");
442 return ERR_WARN;
443}
444
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100445
Willy Tarreaubaaee002006-06-26 02:48:02 +0200446/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200447 * parse a line in a <global> section. Returns the error code, 0 if OK, or
448 * any combination of :
449 * - ERR_ABORT: must abort ASAP
450 * - ERR_FATAL: we can continue parsing but not start the service
451 * - ERR_WARN: a warning has been emitted
452 * - ERR_ALERT: an alert has been emitted
453 * Only the two first ones can stop processing, the two others are just
454 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200456int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457{
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200459 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460
461 if (!strcmp(args[0], "global")) { /* new section */
462 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 }
465 else if (!strcmp(args[0], "daemon")) {
466 global.mode |= MODE_DAEMON;
467 }
468 else if (!strcmp(args[0], "debug")) {
469 global.mode |= MODE_DEBUG;
470 }
471 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100472 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200476 }
477 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100483 else if (!strcmp(args[0], "nosplice")) {
484 global.tune.options &= ~GTUNE_USE_SPLICE;
485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 else if (!strcmp(args[0], "quiet")) {
487 global.mode |= MODE_QUIET;
488 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 else if (!strcmp(args[0], "tune.maxpollevents")) {
490 if (global.tune.maxpollevents != 0) {
491 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 if (*(args[1]) == 0) {
496 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200497 err_code |= ERR_ALERT | ERR_FATAL;
498 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200499 }
500 global.tune.maxpollevents = atol(args[1]);
501 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 else if (!strcmp(args[0], "tune.maxaccept")) {
503 if (global.tune.maxaccept != 0) {
504 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 if (*(args[1]) == 0) {
509 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200510 err_code |= ERR_ALERT | ERR_FATAL;
511 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100512 }
513 global.tune.maxaccept = atol(args[1]);
514 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200515 else if (!strcmp(args[0], "tune.chksize")) {
516 if (*(args[1]) == 0) {
517 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT | ERR_FATAL;
519 goto out;
520 }
521 global.tune.chksize = atol(args[1]);
522 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200523 else if (!strcmp(args[0], "tune.bufsize")) {
524 if (*(args[1]) == 0) {
525 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 global.tune.bufsize = atol(args[1]);
530 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
531 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200532 trashlen = global.tune.bufsize;
533 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200534 }
535 else if (!strcmp(args[0], "tune.maxrewrite")) {
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
540 }
541 global.tune.maxrewrite = atol(args[1]);
542 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
543 global.tune.maxrewrite = global.tune.bufsize / 2;
544 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100545 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
546 if (global.tune.client_rcvbuf != 0) {
547 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT;
549 goto out;
550 }
551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 global.tune.client_rcvbuf = atol(args[1]);
557 }
558 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
559 if (global.tune.server_rcvbuf != 0) {
560 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.tune.server_rcvbuf = atol(args[1]);
570 }
571 else if (!strcmp(args[0], "tune.sndbuf.client")) {
572 if (global.tune.client_sndbuf != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT;
575 goto out;
576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.client_sndbuf = atol(args[1]);
583 }
584 else if (!strcmp(args[0], "tune.sndbuf.server")) {
585 if (global.tune.server_sndbuf != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT;
588 goto out;
589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
594 }
595 global.tune.server_sndbuf = atol(args[1]);
596 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200597 else if (!strcmp(args[0], "tune.pipesize")) {
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.pipesize = atol(args[1]);
604 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200605 else if (!strcmp(args[0], "tune.http.maxhdr")) {
606 if (*(args[1]) == 0) {
607 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610 }
611 global.tune.max_http_hdr = atol(args[1]);
612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 else if (!strcmp(args[0], "uid")) {
614 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200615 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT;
617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 }
619 if (*(args[1]) == 0) {
620 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 global.uid = atol(args[1]);
625 }
626 else if (!strcmp(args[0], "gid")) {
627 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200628 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 global.gid = atol(args[1]);
638 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200639 /* user/group name handling */
640 else if (!strcmp(args[0], "user")) {
641 struct passwd *ha_user;
642 if (global.uid != 0) {
643 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200644 err_code |= ERR_ALERT;
645 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200646 }
647 errno = 0;
648 ha_user = getpwnam(args[1]);
649 if (ha_user != NULL) {
650 global.uid = (int)ha_user->pw_uid;
651 }
652 else {
653 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200654 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200655 }
656 }
657 else if (!strcmp(args[0], "group")) {
658 struct group *ha_group;
659 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200660 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200661 err_code |= ERR_ALERT;
662 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200663 }
664 errno = 0;
665 ha_group = getgrnam(args[1]);
666 if (ha_group != NULL) {
667 global.gid = (int)ha_group->gr_gid;
668 }
669 else {
670 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200671 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200672 }
673 }
674 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "nbproc")) {
676 if (global.nbproc != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.nbproc = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "maxconn")) {
689 if (global.maxconn != 0) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.maxconn = atol(args[1]);
700#ifdef SYSTEM_MAXCONN
701 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
702 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
703 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200704 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 }
706#endif /* SYSTEM_MAXCONN */
707 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200708 else if (!strcmp(args[0], "maxconnrate")) {
709 if (global.cps_lim != 0) {
710 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
711 err_code |= ERR_ALERT;
712 goto out;
713 }
714 if (*(args[1]) == 0) {
715 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
716 err_code |= ERR_ALERT | ERR_FATAL;
717 goto out;
718 }
719 global.cps_lim = atol(args[1]);
720 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100721 else if (!strcmp(args[0], "maxpipes")) {
722 if (global.maxpipes != 0) {
723 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200724 err_code |= ERR_ALERT;
725 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 }
727 if (*(args[1]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100731 }
732 global.maxpipes = atol(args[1]);
733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 else if (!strcmp(args[0], "ulimit-n")) {
735 if (global.rlimit_nofile != 0) {
736 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT;
738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740 if (*(args[1]) == 0) {
741 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 global.rlimit_nofile = atol(args[1]);
746 }
747 else if (!strcmp(args[0], "chroot")) {
748 if (global.chroot != NULL) {
749 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 global.chroot = strdup(args[1]);
759 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200760 else if (!strcmp(args[0], "description")) {
761 int i, len=0;
762 char *d;
763
764 if (!*args[1]) {
765 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
766 file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770
771 for(i=1; *args[i]; i++)
772 len += strlen(args[i])+1;
773
774 if (global.desc)
775 free(global.desc);
776
777 global.desc = d = (char *)calloc(1, len);
778
779 d += sprintf(d, "%s", args[1]);
780 for(i=2; *args[i]; i++)
781 d += sprintf(d, " %s", args[i]);
782 }
783 else if (!strcmp(args[0], "node")) {
784 int i;
785 char c;
786
787 for (i=0; args[1][i]; i++) {
788 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100789 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
790 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200791 break;
792 }
793
794 if (!i || args[1][i]) {
795 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
796 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
797 file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801
802 if (global.node)
803 free(global.node);
804
805 global.node = strdup(args[1]);
806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 else if (!strcmp(args[0], "pidfile")) {
808 if (global.pidfile != NULL) {
809 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT;
811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 if (*(args[1]) == 0) {
814 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 }
818 global.pidfile = strdup(args[1]);
819 }
Emeric Bruned760922010-10-22 17:59:25 +0200820 else if (!strcmp(args[0], "unix-bind")) {
821 int cur_arg = 1;
822 while (*(args[cur_arg])) {
823 if (!strcmp(args[cur_arg], "prefix")) {
824 if (global.unix_bind.prefix != NULL) {
825 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
826 err_code |= ERR_ALERT;
827 cur_arg += 2;
828 continue;
829 }
830
831 if (*(args[cur_arg+1]) == 0) {
832 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836 global.unix_bind.prefix = strdup(args[cur_arg+1]);
837 cur_arg += 2;
838 continue;
839 }
840
841 if (!strcmp(args[cur_arg], "mode")) {
842
843 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
844 cur_arg += 2;
845 continue;
846 }
847
848 if (!strcmp(args[cur_arg], "uid")) {
849
850 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
851 cur_arg += 2;
852 continue;
853 }
854
855 if (!strcmp(args[cur_arg], "gid")) {
856
857 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
858 cur_arg += 2;
859 continue;
860 }
861
862 if (!strcmp(args[cur_arg], "user")) {
863 struct passwd *user;
864
865 user = getpwnam(args[cur_arg + 1]);
866 if (!user) {
867 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
868 file, linenum, args[0], args[cur_arg + 1 ]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872
873 global.unix_bind.ux.uid = user->pw_uid;
874 cur_arg += 2;
875 continue;
876 }
877
878 if (!strcmp(args[cur_arg], "group")) {
879 struct group *group;
880
881 group = getgrnam(args[cur_arg + 1]);
882 if (!group) {
883 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
884 file, linenum, args[0], args[cur_arg + 1 ]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888
889 global.unix_bind.ux.gid = group->gr_gid;
890 cur_arg += 2;
891 continue;
892 }
893
Willy Tarreaub48f9582011-09-05 01:17:06 +0200894 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200895 file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 }
William Lallemand0f99e342011-10-12 17:50:54 +0200900 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
901 /* delete previous herited or defined syslog servers */
902 struct logsrv *back;
903 struct logsrv *tmp;
904
905 if (*(args[1]) != 0) {
906 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910
911 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
912 LIST_DEL(&tmp->list);
913 free(tmp);
914 }
915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200917 struct logsrv *logsrv;
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 if (*(args[1]) == 0 || *(args[2]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 }
William Lallemand0f99e342011-10-12 17:50:54 +0200924
925 logsrv = calloc(1, sizeof(struct logsrv));
926
927 logsrv->facility = get_log_facility(args[2]);
928 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200931 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933
William Lallemand0f99e342011-10-12 17:50:54 +0200934 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200936 logsrv->level = get_log_level(args[3]);
937 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200939 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200940 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941 }
942 }
943
William Lallemand0f99e342011-10-12 17:50:54 +0200944 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200946 logsrv->minlvl = get_log_level(args[4]);
947 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200948 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200950 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200951 }
952 }
953
Robert Tsai81ae1952007-12-05 10:47:29 +0100954 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100955 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100956 if (!sk) {
957 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100958 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100959 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200960 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 goto out;
962 }
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100964 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100965 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100966 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100967 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
968 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200969 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100970 goto out;
971 }
William Lallemand0f99e342011-10-12 17:50:54 +0200972 logsrv->addr = *sk;
973 if (!get_host_port(&logsrv->addr))
974 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976
William Lallemand0f99e342011-10-12 17:50:54 +0200977 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200978 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100979 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
980 char *name;
981 int len;
982
983 if (global.log_send_hostname != NULL) {
984 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT;
986 goto out;
987 }
988
989 if (*(args[1]))
990 name = args[1];
991 else
992 name = hostname;
993
994 len = strlen(name);
995
996 /* We'll add a space after the name to respect the log format */
997 free(global.log_send_hostname);
998 global.log_send_hostname = malloc(len + 2);
999 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1000 }
Kevinm48936af2010-12-22 16:08:21 +00001001 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1002 if (*(args[1]) == 0) {
1003 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007 free(global.log_tag);
1008 global.log_tag = strdup(args[1]);
1009 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1011 if (global.spread_checks != 0) {
1012 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT;
1014 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
1016 if (*(args[1]) == 0) {
1017 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
1021 global.spread_checks = atol(args[1]);
1022 if (global.spread_checks < 0 || global.spread_checks > 50) {
1023 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001024 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 }
1027 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001028 struct cfg_kw_list *kwl;
1029 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001031
1032 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1033 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1034 if (kwl->kw[index].section != CFG_GLOBAL)
1035 continue;
1036 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1037 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001038 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001039 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001040 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001041 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001042 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001043 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001044 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001045 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001046 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_WARN;
1048 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001049 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001051 }
1052 }
1053 }
1054
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001058
Willy Tarreau058e9072009-07-20 09:30:05 +02001059 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001060 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062}
1063
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001064void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001066 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 defproxy.mode = PR_MODE_TCP;
1068 defproxy.state = PR_STNEW;
1069 defproxy.maxconn = cfg_maxpconn;
1070 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001071
1072 defproxy.defsrv.inter = DEF_CHKINTR;
1073 defproxy.defsrv.fastinter = 0;
1074 defproxy.defsrv.downinter = 0;
1075 defproxy.defsrv.rise = DEF_RISETIME;
1076 defproxy.defsrv.fall = DEF_FALLTIME;
1077 defproxy.defsrv.check_port = 0;
1078 defproxy.defsrv.maxqueue = 0;
1079 defproxy.defsrv.minconn = 0;
1080 defproxy.defsrv.maxconn = 0;
1081 defproxy.defsrv.slowstart = 0;
1082 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1083 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1084 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085}
1086
Willy Tarreauade5ec42010-01-28 19:33:49 +01001087
1088static int create_cond_regex_rule(const char *file, int line,
1089 struct proxy *px, int dir, int action, int flags,
1090 const char *cmd, const char *reg, const char *repl,
1091 const char **cond_start)
1092{
1093 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001094 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001095 const char *err;
1096 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001097 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001098
1099 if (px == &defproxy) {
1100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto err;
1103 }
1104
1105 if (*reg == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto err;
1109 }
1110
1111 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1112 err_code |= ERR_WARN;
1113
Willy Tarreau5321c422010-01-28 20:35:13 +01001114 if (cond_start &&
1115 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001116 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1117 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1118 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto err;
1121 }
1122 }
1123 else if (cond_start && **cond_start) {
1124 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1125 file, line, cmd, *cond_start);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto err;
1128 }
1129
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001130 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001131 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001132 else
1133 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001134
Willy Tarreauade5ec42010-01-28 19:33:49 +01001135 preg = calloc(1, sizeof(regex_t));
1136 if (!preg) {
1137 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1138 err_code = ERR_ALERT | ERR_FATAL;
1139 goto err;
1140 }
1141
1142 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1143 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1144 err_code = ERR_ALERT | ERR_FATAL;
1145 goto err;
1146 }
1147
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001148 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001149 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001150 if (repl && err) {
1151 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1152 file, line, cmd, *err);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto err;
1155 }
1156
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001157 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001158 err_code |= ERR_WARN;
1159
Willy Tarreauf4068b62012-05-08 17:37:49 +02001160 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001161 return err_code;
1162 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001163 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001164 free(preg);
1165 return err_code;
1166}
1167
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001169 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001170 * Returns the error code, 0 if OK, or any combination of :
1171 * - ERR_ABORT: must abort ASAP
1172 * - ERR_FATAL: we can continue parsing but not start the service
1173 * - ERR_WARN: a warning has been emitted
1174 * - ERR_ALERT: an alert has been emitted
1175 * Only the two first ones can stop processing, the two others are just
1176 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001178int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1179{
1180 static struct peers *curpeers = NULL;
1181 struct peer *newpeer = NULL;
1182 const char *err;
1183 int err_code = 0;
1184
1185 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1186
1187 err = invalid_char(args[1]);
1188 if (err) {
1189 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1190 file, linenum, *err, args[0], args[1]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 }
1193
1194 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1195 /*
1196 * If there are two proxies with the same name only following
1197 * combinations are allowed:
1198 */
1199 if (strcmp(curpeers->id, args[1]) == 0) {
1200 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1201 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1202 err_code |= ERR_WARN;
1203 }
1204 }
1205
1206 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1207 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1208 err_code |= ERR_ALERT | ERR_ABORT;
1209 goto out;
1210 }
1211
1212 curpeers->next = peers;
1213 peers = curpeers;
1214 curpeers->conf.file = file;
1215 curpeers->conf.line = linenum;
1216 curpeers->last_change = now.tv_sec;
1217 curpeers->id = strdup(args[1]);
1218 }
1219 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1220 char *rport, *raddr;
1221 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001222 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001223
1224 if (!*args[2]) {
1225 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1226 file, linenum, args[0]);
1227 err_code |= ERR_ALERT | ERR_FATAL;
1228 goto out;
1229 }
1230
1231 err = invalid_char(args[1]);
1232 if (err) {
1233 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1234 file, linenum, *err, args[1]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1240 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1241 err_code |= ERR_ALERT | ERR_ABORT;
1242 goto out;
1243 }
1244
1245 /* the peers are linked backwards first */
1246 curpeers->count++;
1247 newpeer->next = curpeers->remote;
1248 curpeers->remote = newpeer;
1249 newpeer->peers = curpeers;
1250 newpeer->conf.file = file;
1251 newpeer->conf.line = linenum;
1252
1253 newpeer->last_change = now.tv_sec;
1254 newpeer->id = strdup(args[1]);
1255
1256 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001257 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001258 if (rport) {
1259 *rport++ = 0;
1260 realport = atol(rport);
1261 }
1262 if (!realport) {
1263 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto out;
1266 }
1267
Willy Tarreaufab5a432011-03-04 15:31:53 +01001268 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001269 free(raddr);
1270 if (!sk) {
1271 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
1275 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001276 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02001277 newpeer->sock = &sock_raw;
1278 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001279
1280 if (!sk) {
1281 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1282 file, linenum, newpeer->addr.ss_family, args[2]);
1283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
1285 }
1286
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001287 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001288
1289 if (strcmp(newpeer->id, localpeer) == 0) {
1290 /* Current is local peer, it define a frontend */
1291 newpeer->local = 1;
1292
1293 if (!curpeers->peers_fe) {
1294 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1296 err_code |= ERR_ALERT | ERR_ABORT;
1297 goto out;
1298 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001299
Willy Tarreau237250c2011-07-29 01:49:03 +02001300 init_new_proxy(curpeers->peers_fe);
1301 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001302
1303 curpeers->peers_fe->last_change = now.tv_sec;
1304 curpeers->peers_fe->id = strdup(args[1]);
1305 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001306 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001307 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1308 curpeers->peers_fe->timeout.connect = 5000;
1309 curpeers->peers_fe->accept = peer_accept;
1310 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001311 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001312 err_code |= ERR_FATAL;
1313 goto out;
1314 }
1315 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1316 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1317 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1318 curpeers->peers_fe->listen->accept = session_accept;
1319 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1320 curpeers->peers_fe->listen->handler = process_session;
1321 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001322 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1323 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001324 }
1325 }
1326 } /* neither "peer" nor "peers" */
1327 else if (*args[0] != 0) {
1328 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332
1333out:
1334 return err_code;
1335}
1336
1337
Willy Tarreau3842f002009-06-14 11:39:52 +02001338int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339{
1340 static struct proxy *curproxy = NULL;
1341 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001342 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001343 int rc;
1344 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001345 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001346 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001347 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001348 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349
Willy Tarreau977b8e42006-12-29 14:19:17 +01001350 if (!strcmp(args[0], "listen"))
1351 rc = PR_CAP_LISTEN;
1352 else if (!strcmp(args[0], "frontend"))
1353 rc = PR_CAP_FE | PR_CAP_RS;
1354 else if (!strcmp(args[0], "backend"))
1355 rc = PR_CAP_BE | PR_CAP_RS;
1356 else if (!strcmp(args[0], "ruleset"))
1357 rc = PR_CAP_RS;
1358 else
1359 rc = PR_CAP_NONE;
1360
1361 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 if (!*args[1]) {
1363 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1364 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001366 err_code |= ERR_ALERT | ERR_ABORT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001369
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001370 err = invalid_char(args[1]);
1371 if (err) {
1372 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1373 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001375 }
1376
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001377 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1378 /*
1379 * If there are two proxies with the same name only following
1380 * combinations are allowed:
1381 *
1382 * listen backend frontend ruleset
1383 * listen - - - -
1384 * backend - - OK -
1385 * frontend - OK - -
1386 * ruleset - - - -
1387 */
1388
1389 if (!strcmp(curproxy->id, args[1]) &&
1390 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1391 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001392 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1393 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1394 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001396 }
1397 }
1398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001401 err_code |= ERR_ALERT | ERR_ABORT;
1402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001404
Willy Tarreau97cb7802010-01-03 20:23:58 +01001405 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 curproxy->next = proxy;
1407 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001408 curproxy->conf.file = file;
1409 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001410 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001412 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413
1414 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001415 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001416 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001417 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001418 err_code |= ERR_FATAL;
1419 goto out;
1420 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001421 new = curproxy->listen;
1422 while (new != last) {
1423 new->conf.file = file;
1424 new->conf.line = linenum;
1425 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001426 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428 }
1429
1430 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001431 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001432 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001433
Willy Tarreaubaaee002006-06-26 02:48:02 +02001434 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001436 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001437 curproxy->no_options = defproxy.no_options;
1438 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001439 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001440 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001441 curproxy->except_net = defproxy.except_net;
1442 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001443 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001444 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001446 if (defproxy.fwdfor_hdr_len) {
1447 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1448 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1449 }
1450
Willy Tarreaub86db342009-11-30 11:50:16 +01001451 if (defproxy.orgto_hdr_len) {
1452 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1453 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1454 }
1455
Mark Lamourinec2247f02012-01-04 13:02:01 -05001456 if (defproxy.server_id_hdr_len) {
1457 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1458 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1459 }
1460
Willy Tarreau977b8e42006-12-29 14:19:17 +01001461 if (curproxy->cap & PR_CAP_FE) {
1462 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001463 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001464 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465
1466 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001467 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1468 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469
1470 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472
Willy Tarreau977b8e42006-12-29 14:19:17 +01001473 if (curproxy->cap & PR_CAP_BE) {
1474 curproxy->fullconn = defproxy.fullconn;
1475 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001477 if (defproxy.check_req) {
1478 curproxy->check_req = calloc(1, defproxy.check_len);
1479 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1480 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001481 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001483 if (defproxy.expect_str) {
1484 curproxy->expect_str = strdup(defproxy.expect_str);
1485 if (defproxy.expect_regex) {
1486 /* note: this regex is known to be valid */
1487 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1488 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1489 }
1490 }
1491
Willy Tarreau67402132012-05-31 20:40:20 +02001492 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 if (defproxy.cookie_name)
1494 curproxy->cookie_name = strdup(defproxy.cookie_name);
1495 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001496 if (defproxy.cookie_domain)
1497 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001498
Willy Tarreau31936852010-10-06 16:59:56 +02001499 if (defproxy.cookie_maxidle)
1500 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1501
1502 if (defproxy.cookie_maxlife)
1503 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1504
Emeric Brun647caf12009-06-30 17:57:00 +02001505 if (defproxy.rdp_cookie_name)
1506 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1507 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1508
Willy Tarreau01732802007-11-01 22:48:15 +01001509 if (defproxy.url_param_name)
1510 curproxy->url_param_name = strdup(defproxy.url_param_name);
1511 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001512
Benoitaffb4812009-03-25 13:02:10 +01001513 if (defproxy.hh_name)
1514 curproxy->hh_name = strdup(defproxy.hh_name);
1515 curproxy->hh_len = defproxy.hh_len;
1516 curproxy->hh_match_domain = defproxy.hh_match_domain;
1517
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001518 if (defproxy.iface_name)
1519 curproxy->iface_name = strdup(defproxy.iface_name);
1520 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001523 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 if (defproxy.capture_name)
1525 curproxy->capture_name = strdup(defproxy.capture_name);
1526 curproxy->capture_namelen = defproxy.capture_namelen;
1527 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529
Willy Tarreau977b8e42006-12-29 14:19:17 +01001530 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001531 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001532 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001533 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001534 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001535 curproxy->uri_auth = defproxy.uri_auth;
1536 curproxy->mon_net = defproxy.mon_net;
1537 curproxy->mon_mask = defproxy.mon_mask;
1538 if (defproxy.monitor_uri)
1539 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1540 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001541 if (defproxy.defbe.name)
1542 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001543
1544 /* get either a pointer to the logformat string or a copy of it */
1545 curproxy->logformat_string = defproxy.logformat_string;
1546 if (curproxy->logformat_string &&
1547 curproxy->logformat_string != default_http_log_format &&
1548 curproxy->logformat_string != default_tcp_log_format &&
1549 curproxy->logformat_string != clf_http_log_format)
1550 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001551 }
1552
1553 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001554 curproxy->timeout.connect = defproxy.timeout.connect;
1555 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001556 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001557 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001558 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001559 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001560 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001561 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001562 curproxy->source_addr = defproxy.source_addr;
1563 }
1564
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001566
1567 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001568 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001569 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001570 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001571 LIST_INIT(&node->list);
1572 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1573 }
1574
Willy Tarreau196729e2012-05-31 19:30:26 +02001575 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1576 if (curproxy->uniqueid_format_string)
1577 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001578
1579 /* copy default header unique id */
1580 if (defproxy.header_unique_id)
1581 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1582
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001584 curproxy->conf.used_listener_id = EB_ROOT;
1585 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001586
Willy Tarreau93893792009-07-23 13:19:11 +02001587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
1589 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1590 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001591 /* FIXME-20070101: we should do this too at the end of the
1592 * config parsing to free all default values.
1593 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001594 free(defproxy.check_req);
1595 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001596 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001597 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001598 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001599 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001600 free(defproxy.capture_name);
1601 free(defproxy.monitor_uri);
1602 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001603 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001604 free(defproxy.fwdfor_hdr_name);
1605 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001606 free(defproxy.orgto_hdr_name);
1607 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001608 free(defproxy.server_id_hdr_name);
1609 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001610 free(defproxy.expect_str);
1611 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001612
Willy Tarreau196729e2012-05-31 19:30:26 +02001613 if (defproxy.logformat_string == default_http_log_format ||
1614 defproxy.logformat_string == default_tcp_log_format ||
1615 defproxy.logformat_string == clf_http_log_format)
1616 free(defproxy.logformat_string);
1617
1618 free(defproxy.uniqueid_format_string);
1619
Willy Tarreaua534fea2008-08-03 12:19:50 +02001620 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001621 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001622
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 /* we cannot free uri_auth because it might already be used */
1624 init_default_instance();
1625 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001626 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 }
1629 else if (curproxy == NULL) {
1630 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 }
1634
Willy Tarreau977b8e42006-12-29 14:19:17 +01001635
1636 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001638 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001639 int cur_arg;
1640
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 if (curproxy == &defproxy) {
1642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001643 err_code |= ERR_ALERT | ERR_FATAL;
1644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001646 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001647 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648
Emeric Bruned760922010-10-22 17:59:25 +02001649 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001650 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001655
1656 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001657
1658 /* NOTE: the following line might create several listeners if there
1659 * are comma-separated IPs or port ranges. So all further processing
1660 * will have to be applied to all listeners created after last_listen.
1661 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001662 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
1665 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001666
Willy Tarreau90a570f2009-10-04 20:54:54 +02001667 new_listen = curproxy->listen;
1668 while (new_listen != last_listen) {
1669 new_listen->conf.file = file;
1670 new_listen->conf.line = linenum;
1671 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001672 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001673 }
1674
Emeric Bruned760922010-10-22 17:59:25 +02001675 /* Set default global rights and owner for unix bind */
1676 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1677 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1678 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001679 cur_arg = 2;
1680 while (*(args[cur_arg])) {
1681 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1682#ifdef SO_BINDTODEVICE
1683 struct listener *l;
1684
Emeric Bruned760922010-10-22 17:59:25 +02001685 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1686 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1687 file, linenum, args[0], args[cur_arg]);
1688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
1690 }
1691
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001692 if (!*args[cur_arg + 1]) {
1693 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1694 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001697 }
1698
1699 for (l = curproxy->listen; l != last_listen; l = l->next)
1700 l->interface = strdup(args[cur_arg + 1]);
1701
1702 global.last_checks |= LSTCHK_NETADM;
1703
1704 cur_arg += 2;
1705 continue;
1706#else
1707 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1708 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001711#endif
1712 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001713 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1714#ifdef TCP_MAXSEG
1715 struct listener *l;
1716 int mss;
1717
Emeric Bruned760922010-10-22 17:59:25 +02001718 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1719 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1720 file, linenum, args[0], args[cur_arg]);
1721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
1724
Willy Tarreaube1b9182009-06-14 18:48:19 +02001725 if (!*args[cur_arg + 1]) {
1726 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1727 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001730 }
1731
Willy Tarreau48a7e722010-12-24 15:26:39 +01001732 mss = atoi(args[cur_arg + 1]);
1733 if (!mss || abs(mss) > 65535) {
1734 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001735 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001736 err_code |= ERR_ALERT | ERR_FATAL;
1737 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001738 }
1739
1740 for (l = curproxy->listen; l != last_listen; l = l->next)
1741 l->maxseg = mss;
1742
1743 cur_arg += 2;
1744 continue;
1745#else
1746 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1747 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001748 err_code |= ERR_ALERT | ERR_FATAL;
1749 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001750#endif
1751 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001752
1753 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1754#ifdef TCP_DEFER_ACCEPT
1755 struct listener *l;
1756
1757 for (l = curproxy->listen; l != last_listen; l = l->next)
1758 l->options |= LI_O_DEF_ACCEPT;
1759
1760 cur_arg ++;
1761 continue;
1762#else
1763 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1764 file, linenum, args[0], args[cur_arg]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767#endif
1768 }
1769
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001770 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001771#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001772 struct listener *l;
1773
Emeric Bruned760922010-10-22 17:59:25 +02001774 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1775 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1776 file, linenum, args[0], args[cur_arg]);
1777 err_code |= ERR_ALERT | ERR_FATAL;
1778 goto out;
1779 }
1780
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001781 for (l = curproxy->listen; l != last_listen; l = l->next)
1782 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001783
1784 cur_arg ++;
1785 continue;
1786#else
1787 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1788 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001791#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001792 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001793
Willy Tarreau8a956912010-10-15 14:27:08 +02001794 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1795 struct listener *l;
1796
1797 for (l = curproxy->listen; l != last_listen; l = l->next)
1798 l->options |= LI_O_ACC_PROXY;
1799
1800 cur_arg ++;
1801 continue;
1802 }
1803
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001804 if (!strcmp(args[cur_arg], "name")) {
1805 struct listener *l;
1806
1807 for (l = curproxy->listen; l != last_listen; l = l->next)
1808 l->name = strdup(args[cur_arg + 1]);
1809
1810 cur_arg += 2;
1811 continue;
1812 }
1813
1814 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001815 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001816 struct listener *l;
1817
1818 if (curproxy->listen->next != last_listen) {
1819 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1820 file, linenum, args[cur_arg]);
1821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
1823 }
1824
1825 if (!*args[cur_arg + 1]) {
1826 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1827 file, linenum, args[cur_arg]);
1828 err_code |= ERR_ALERT | ERR_FATAL;
1829 goto out;
1830 }
1831
1832 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001833 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001834
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001835 if (curproxy->listen->luid <= 0) {
1836 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001837 file, linenum);
1838 err_code |= ERR_ALERT | ERR_FATAL;
1839 goto out;
1840 }
1841
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001842 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1843 if (node) {
1844 l = container_of(node, struct listener, conf.id);
1845 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1846 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
1849 }
1850 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1851
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001852 cur_arg += 2;
1853 continue;
1854 }
1855
Emeric Bruned760922010-10-22 17:59:25 +02001856 if (!strcmp(args[cur_arg], "mode")) {
1857
1858 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1859 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1860 file, linenum, args[0], args[cur_arg]);
1861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
1863 }
1864
1865 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1866
1867 cur_arg += 2;
1868 continue;
1869 }
1870
1871 if (!strcmp(args[cur_arg], "uid")) {
1872
1873 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1874 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1875 file, linenum, args[0], args[cur_arg]);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879
1880 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1881 cur_arg += 2;
1882 continue;
1883 }
1884
1885 if (!strcmp(args[cur_arg], "gid")) {
1886
1887 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1888 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1889 file, linenum, args[0], args[cur_arg]);
1890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
1892 }
1893
1894 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1895 cur_arg += 2;
1896 continue;
1897 }
1898
1899 if (!strcmp(args[cur_arg], "user")) {
1900 struct passwd *user;
1901
1902 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1903 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1904 file, linenum, args[0], args[cur_arg]);
1905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
1907 }
1908 user = getpwnam(args[cur_arg + 1]);
1909 if (!user) {
1910 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1911 file, linenum, args[0], args[cur_arg + 1 ]);
1912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
1914 }
1915
1916 curproxy->listen->perm.ux.uid = user->pw_uid;
1917 cur_arg += 2;
1918 continue;
1919 }
1920
1921 if (!strcmp(args[cur_arg], "group")) {
1922 struct group *group;
1923
1924 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1925 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1926 file, linenum, args[0], args[cur_arg]);
1927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
1929 }
1930 group = getgrnam(args[cur_arg + 1]);
1931 if (!group) {
1932 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1933 file, linenum, args[0], args[cur_arg + 1 ]);
1934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
1936 }
1937
1938 curproxy->listen->perm.ux.gid = group->gr_gid;
1939 cur_arg += 2;
1940 continue;
1941 }
1942
Willy Tarreaub48f9582011-09-05 01:17:06 +02001943 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 +01001944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001945 err_code |= ERR_ALERT | ERR_FATAL;
1946 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001947 }
Willy Tarreau93893792009-07-23 13:19:11 +02001948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 }
1950 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1951 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1952 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_ALERT | ERR_FATAL;
1955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959
Willy Tarreaubaaee002006-06-26 02:48:02 +02001960 /* flush useless bits */
1961 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001964 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001965 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001967
Willy Tarreau1c47f852006-07-09 08:22:27 +02001968 if (!*args[1]) {
1969 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1970 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001973 }
1974
Willy Tarreaua534fea2008-08-03 12:19:50 +02001975 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001976 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001977 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001978 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001979 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1980
Willy Tarreau93893792009-07-23 13:19:11 +02001981 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1984 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1985 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1986 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1987 else {
1988 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 }
1992 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001993 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001994 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001995
1996 if (curproxy == &defproxy) {
1997 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1998 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002001 }
2002
2003 if (!*args[1]) {
2004 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2005 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002008 }
2009
2010 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002011 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002012
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002013 if (curproxy->uuid <= 0) {
2014 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002015 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002018 }
2019
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002020 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2021 if (node) {
2022 struct proxy *target = container_of(node, struct proxy, conf.id);
2023 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2024 file, linenum, proxy_type_str(curproxy), curproxy->id,
2025 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
2028 }
2029 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002030 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002031 else if (!strcmp(args[0], "description")) {
2032 int i, len=0;
2033 char *d;
2034
Cyril Bonté99ed3272010-01-24 23:29:44 +01002035 if (curproxy == &defproxy) {
2036 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2037 file, linenum, args[0]);
2038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
2041
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002042 if (!*args[1]) {
2043 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2044 file, linenum, args[0]);
2045 return -1;
2046 }
2047
2048 for(i=1; *args[i]; i++)
2049 len += strlen(args[i])+1;
2050
2051 d = (char *)calloc(1, len);
2052 curproxy->desc = d;
2053
2054 d += sprintf(d, "%s", args[1]);
2055 for(i=2; *args[i]; i++)
2056 d += sprintf(d, " %s", args[i]);
2057
2058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2060 curproxy->state = PR_STSTOPPED;
2061 }
2062 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2063 curproxy->state = PR_STNEW;
2064 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002065 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2066 int cur_arg = 1;
2067 unsigned int set = 0;
2068
2069 while (*args[cur_arg]) {
2070 int u;
2071 if (strcmp(args[cur_arg], "all") == 0) {
2072 set = 0;
2073 break;
2074 }
2075 else if (strcmp(args[cur_arg], "odd") == 0) {
2076 set |= 0x55555555;
2077 }
2078 else if (strcmp(args[cur_arg], "even") == 0) {
2079 set |= 0xAAAAAAAA;
2080 }
2081 else {
2082 u = str2uic(args[cur_arg]);
2083 if (u < 1 || u > 32) {
2084 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2085 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002088 }
2089 if (u > global.nbproc) {
2090 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2091 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002093 }
2094 set |= 1 << (u - 1);
2095 }
2096 cur_arg++;
2097 }
2098 curproxy->bind_proc = set;
2099 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002100 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002101 if (curproxy == &defproxy) {
2102 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002105 }
2106
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002107 err = invalid_char(args[1]);
2108 if (err) {
2109 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2110 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002111 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002112 }
2113
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002114 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2115 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2116 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002119 }
2120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2122 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123
Willy Tarreau977b8e42006-12-29 14:19:17 +01002124 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002125 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002126
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 if (*(args[1]) == 0) {
2128 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2129 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002133
Willy Tarreau67402132012-05-31 20:40:20 +02002134 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002135 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002136 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002137 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 curproxy->cookie_name = strdup(args[1]);
2139 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002140
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 cur_arg = 2;
2142 while (*(args[cur_arg])) {
2143 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002144 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
2146 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002147 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 }
2149 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002150 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 }
2152 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002153 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 }
2155 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002156 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002157 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002158 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002159 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002162 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002164 else if (!strcmp(args[cur_arg], "httponly")) {
2165 curproxy->ck_opts |= PR_CK_HTTPONLY;
2166 }
2167 else if (!strcmp(args[cur_arg], "secure")) {
2168 curproxy->ck_opts |= PR_CK_SECURE;
2169 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002170 else if (!strcmp(args[cur_arg], "domain")) {
2171 if (!*args[cur_arg + 1]) {
2172 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2173 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002176 }
2177
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002178 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002179 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002180 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2181 " dots nor does not start with a dot."
2182 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002183 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002184 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002185 }
2186
2187 err = invalid_domainchar(args[cur_arg + 1]);
2188 if (err) {
2189 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2190 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002193 }
2194
Willy Tarreau68a897b2009-12-03 23:28:34 +01002195 if (!curproxy->cookie_domain) {
2196 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2197 } else {
2198 /* one domain was already specified, add another one by
2199 * building the string which will be returned along with
2200 * the cookie.
2201 */
2202 char *new_ptr;
2203 int new_len = strlen(curproxy->cookie_domain) +
2204 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2205 new_ptr = malloc(new_len);
2206 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2207 free(curproxy->cookie_domain);
2208 curproxy->cookie_domain = new_ptr;
2209 }
Willy Tarreau31936852010-10-06 16:59:56 +02002210 cur_arg++;
2211 }
2212 else if (!strcmp(args[cur_arg], "maxidle")) {
2213 unsigned int maxidle;
2214 const char *res;
2215
2216 if (!*args[cur_arg + 1]) {
2217 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2218 file, linenum, args[cur_arg]);
2219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
2221 }
2222
2223 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2224 if (res) {
2225 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2226 file, linenum, *res, args[cur_arg]);
2227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
2229 }
2230 curproxy->cookie_maxidle = maxidle;
2231 cur_arg++;
2232 }
2233 else if (!strcmp(args[cur_arg], "maxlife")) {
2234 unsigned int maxlife;
2235 const char *res;
2236
2237 if (!*args[cur_arg + 1]) {
2238 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2239 file, linenum, args[cur_arg]);
2240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
2242 }
2243
2244 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2245 if (res) {
2246 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2247 file, linenum, *res, args[cur_arg]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002252 cur_arg++;
2253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002255 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 +02002256 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 }
2260 cur_arg++;
2261 }
Willy Tarreau67402132012-05-31 20:40:20 +02002262 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2264 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
2267
Willy Tarreau67402132012-05-31 20:40:20 +02002268 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2270 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002273
Willy Tarreau67402132012-05-31 20:40:20 +02002274 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002275 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2276 file, linenum);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002280 else if (!strcmp(args[0], "persist")) { /* persist */
2281 if (*(args[1]) == 0) {
2282 Alert("parsing [%s:%d] : missing persist method.\n",
2283 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002286 }
2287
2288 if (!strncmp(args[1], "rdp-cookie", 10)) {
2289 curproxy->options2 |= PR_O2_RDPC_PRST;
2290
Emeric Brunb982a3d2010-01-04 15:45:53 +01002291 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002292 const char *beg, *end;
2293
2294 beg = args[1] + 11;
2295 end = strchr(beg, ')');
2296
2297 if (!end || end == beg) {
2298 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2299 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002302 }
2303
2304 free(curproxy->rdp_cookie_name);
2305 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2306 curproxy->rdp_cookie_len = end-beg;
2307 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002308 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002309 free(curproxy->rdp_cookie_name);
2310 curproxy->rdp_cookie_name = strdup("msts");
2311 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2312 }
2313 else { /* syntax */
2314 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2315 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002318 }
2319 }
2320 else {
2321 Alert("parsing [%s:%d] : unknown persist method.\n",
2322 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002325 }
2326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002328 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002330 if (curproxy == &defproxy) {
2331 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335
Willy Tarreau977b8e42006-12-29 14:19:17 +01002336 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002340 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 }
2345 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002346 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 curproxy->appsession_name = strdup(args[1]);
2348 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2349 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002350 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2351 if (err) {
2352 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2353 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002356 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002357 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002358
Willy Tarreau51041c72007-09-09 21:56:53 +02002359 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002361 err_code |= ERR_ALERT | ERR_ABORT;
2362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002364
2365 cur_arg = 6;
2366 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002367 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2368 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002369 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002370 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002371 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002372 } else if (!strcmp(args[cur_arg], "prefix")) {
2373 curproxy->options2 |= PR_O2_AS_PFX;
2374 } else if (!strcmp(args[cur_arg], "mode")) {
2375 if (!*args[cur_arg + 1]) {
2376 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2377 file, linenum, args[0], args[cur_arg]);
2378 err_code |= ERR_ALERT | ERR_FATAL;
2379 goto out;
2380 }
2381
2382 cur_arg++;
2383 if (!strcmp(args[cur_arg], "query-string")) {
2384 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2385 curproxy->options2 |= PR_O2_AS_M_QS;
2386 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2387 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2388 curproxy->options2 |= PR_O2_AS_M_PP;
2389 } else {
2390 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
2393 }
2394 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002395 cur_arg++;
2396 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 } /* Url App Session */
2398 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002399 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002401
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002403 if (curproxy == &defproxy) {
2404 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
2407 }
2408
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 if (*(args[4]) == 0) {
2410 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2411 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002415 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 curproxy->capture_name = strdup(args[2]);
2417 curproxy->capture_namelen = strlen(curproxy->capture_name);
2418 curproxy->capture_len = atol(args[4]);
2419 if (curproxy->capture_len >= CAPTURE_LEN) {
2420 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2421 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 curproxy->capture_len = CAPTURE_LEN - 1;
2424 }
2425 curproxy->to_log |= LW_COOKIE;
2426 }
2427 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2428 struct cap_hdr *hdr;
2429
2430 if (curproxy == &defproxy) {
2431 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 +02002432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435
2436 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2437 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2438 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }
2442
2443 hdr = calloc(sizeof(struct cap_hdr), 1);
2444 hdr->next = curproxy->req_cap;
2445 hdr->name = strdup(args[3]);
2446 hdr->namelen = strlen(args[3]);
2447 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002448 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 hdr->index = curproxy->nb_req_cap++;
2450 curproxy->req_cap = hdr;
2451 curproxy->to_log |= LW_REQHDR;
2452 }
2453 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2454 struct cap_hdr *hdr;
2455
2456 if (curproxy == &defproxy) {
2457 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 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 }
2461
2462 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2463 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2464 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
2468 hdr = calloc(sizeof(struct cap_hdr), 1);
2469 hdr->next = curproxy->rsp_cap;
2470 hdr->name = strdup(args[3]);
2471 hdr->namelen = strlen(args[3]);
2472 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002473 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 hdr->index = curproxy->nb_rsp_cap++;
2475 curproxy->rsp_cap = hdr;
2476 curproxy->to_log |= LW_RSPHDR;
2477 }
2478 else {
2479 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 }
2484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002486 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 if (*(args[1]) == 0) {
2490 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 }
2495 curproxy->conn_retries = atol(args[1]);
2496 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002497 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002498 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002499
2500 if (curproxy == &defproxy) {
2501 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
2505
Willy Tarreauff011f22011-01-06 17:51:27 +01002506 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 +01002507 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2508 file, linenum, args[0]);
2509 err_code |= ERR_WARN;
2510 }
2511
Willy Tarreauff011f22011-01-06 17:51:27 +01002512 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002513
Willy Tarreauff011f22011-01-06 17:51:27 +01002514 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002515 err_code |= ERR_ALERT | ERR_ABORT;
2516 goto out;
2517 }
2518
Willy Tarreauff011f22011-01-06 17:51:27 +01002519 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2520 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002521 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002522 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2523 /* set the header name and length into the proxy structure */
2524 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2525 err_code |= ERR_WARN;
2526
2527 if (!*args[1]) {
2528 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2529 file, linenum, args[0]);
2530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
2532 }
2533
2534 /* set the desired header name */
2535 free(curproxy->server_id_hdr_name);
2536 curproxy->server_id_hdr_name = strdup(args[1]);
2537 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2538 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002539 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002540 if (curproxy == &defproxy) {
2541 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002544 }
2545
Willy Tarreauef6494c2010-01-28 17:12:36 +01002546 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002547 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2548 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002551 }
2552
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002553 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2554 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2555 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002558 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002559
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002560 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002561 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002562 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002564 struct redirect_rule *rule;
2565 int cur_arg;
2566 int type = REDIRECT_TYPE_NONE;
2567 int code = 302;
2568 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002569 char *cookie = NULL;
2570 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002571 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002572
Cyril Bonté99ed3272010-01-24 23:29:44 +01002573 if (curproxy == &defproxy) {
2574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
2577 }
2578
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 cur_arg = 1;
2580 while (*(args[cur_arg])) {
2581 if (!strcmp(args[cur_arg], "location")) {
2582 if (!*args[cur_arg + 1]) {
2583 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2584 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002587 }
2588
2589 type = REDIRECT_TYPE_LOCATION;
2590 cur_arg++;
2591 destination = args[cur_arg];
2592 }
2593 else if (!strcmp(args[cur_arg], "prefix")) {
2594 if (!*args[cur_arg + 1]) {
2595 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2596 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002599 }
2600
2601 type = REDIRECT_TYPE_PREFIX;
2602 cur_arg++;
2603 destination = args[cur_arg];
2604 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002605 else if (!strcmp(args[cur_arg], "set-cookie")) {
2606 if (!*args[cur_arg + 1]) {
2607 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2608 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002611 }
2612
2613 cur_arg++;
2614 cookie = args[cur_arg];
2615 cookie_set = 1;
2616 }
2617 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2618 if (!*args[cur_arg + 1]) {
2619 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2620 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002623 }
2624
2625 cur_arg++;
2626 cookie = args[cur_arg];
2627 cookie_set = 0;
2628 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002629 else if (!strcmp(args[cur_arg],"code")) {
2630 if (!*args[cur_arg + 1]) {
2631 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2632 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002633 err_code |= ERR_ALERT | ERR_FATAL;
2634 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002635 }
2636 cur_arg++;
2637 code = atol(args[cur_arg]);
2638 if (code < 301 || code > 303) {
2639 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2640 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002643 }
2644 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002645 else if (!strcmp(args[cur_arg],"drop-query")) {
2646 flags |= REDIRECT_FLAG_DROP_QS;
2647 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002648 else if (!strcmp(args[cur_arg],"append-slash")) {
2649 flags |= REDIRECT_FLAG_APPEND_SLASH;
2650 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002651 else if (strcmp(args[cur_arg], "if") == 0 ||
2652 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002653 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002654 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002655 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2656 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
2659 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002660 break;
2661 }
2662 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002663 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 +02002664 file, linenum, args[0], args[cur_arg]);
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 cur_arg++;
2669 }
2670
2671 if (type == REDIRECT_TYPE_NONE) {
2672 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2673 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002676 }
2677
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002678 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2679 rule->cond = cond;
2680 rule->rdr_str = strdup(destination);
2681 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002682 if (cookie) {
2683 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002684 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002685 */
2686 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002687 if (cookie_set) {
2688 rule->cookie_str = malloc(rule->cookie_len + 10);
2689 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2690 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2691 rule->cookie_len += 9;
2692 } else {
2693 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002694 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002695 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2696 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002697 }
2698 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002699 rule->type = type;
2700 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002701 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002702 LIST_INIT(&rule->list);
2703 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002704 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2705 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002706 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002707 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002708 struct switching_rule *rule;
2709
Willy Tarreaub099aca2008-10-12 17:26:37 +02002710 if (curproxy == &defproxy) {
2711 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002714 }
2715
Willy Tarreau55ea7572007-06-17 19:56:27 +02002716 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002718
2719 if (*(args[1]) == 0) {
2720 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002723 }
2724
Willy Tarreauef6494c2010-01-28 17:12:36 +01002725 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002726 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2727 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002730 }
2731
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002732 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2733 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2734 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002737 }
2738
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002739 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002740
Willy Tarreau55ea7572007-06-17 19:56:27 +02002741 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2742 rule->cond = cond;
2743 rule->be.name = strdup(args[1]);
2744 LIST_INIT(&rule->list);
2745 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2746 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002747 else if (strcmp(args[0], "use-server") == 0) {
2748 struct server_rule *rule;
2749
2750 if (curproxy == &defproxy) {
2751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
2756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2757 err_code |= ERR_WARN;
2758
2759 if (*(args[1]) == 0) {
2760 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
2763 }
2764
2765 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2766 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2767 file, linenum, args[0]);
2768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
2771
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002772 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2773 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2774 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778
2779 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2780
2781 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2782 rule->cond = cond;
2783 rule->srv.name = strdup(args[1]);
2784 LIST_INIT(&rule->list);
2785 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2786 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2787 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002788 else if ((!strcmp(args[0], "force-persist")) ||
2789 (!strcmp(args[0], "ignore-persist"))) {
2790 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002791
2792 if (curproxy == &defproxy) {
2793 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
2796 }
2797
2798 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2799 err_code |= ERR_WARN;
2800
Willy Tarreauef6494c2010-01-28 17:12:36 +01002801 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002802 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2803 file, linenum, args[0]);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002808 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2809 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2810 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
2813 }
2814
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002815 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002816
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002817 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002818 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002819 if (!strcmp(args[0], "force-persist")) {
2820 rule->type = PERSIST_TYPE_FORCE;
2821 } else {
2822 rule->type = PERSIST_TYPE_IGNORE;
2823 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002824 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002825 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002826 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002827 else if (!strcmp(args[0], "stick-table")) {
2828 int myidx = 1;
2829
Emeric Brun32da3c42010-09-23 18:39:19 +02002830 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002831 curproxy->table.type = (unsigned int)-1;
2832 while (*args[myidx]) {
2833 const char *err;
2834
2835 if (strcmp(args[myidx], "size") == 0) {
2836 myidx++;
2837 if (!*(args[myidx])) {
2838 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2839 file, linenum, args[myidx-1]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2844 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2845 file, linenum, *err, args[myidx-1]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002849 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002850 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002851 else if (strcmp(args[myidx], "peers") == 0) {
2852 myidx++;
2853 if (!*(args[myidx])) {
2854 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2855 file, linenum, args[myidx-1]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859 curproxy->table.peers.name = strdup(args[myidx++]);
2860 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002861 else if (strcmp(args[myidx], "expire") == 0) {
2862 myidx++;
2863 if (!*(args[myidx])) {
2864 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2865 file, linenum, args[myidx-1]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2870 if (err) {
2871 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2872 file, linenum, *err, args[myidx-1]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002877 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002878 }
2879 else if (strcmp(args[myidx], "nopurge") == 0) {
2880 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002881 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002882 }
2883 else if (strcmp(args[myidx], "type") == 0) {
2884 myidx++;
2885 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2886 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2887 file, linenum, args[myidx]);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002891 /* myidx already points to next arg */
2892 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002893 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002894 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002895 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002896
2897 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002898 nw = args[myidx];
2899 while (*nw) {
2900 /* the "store" keyword supports a comma-separated list */
2901 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002902 sa = NULL; /* store arg */
2903 while (*nw && *nw != ',') {
2904 if (*nw == '(') {
2905 *nw = 0;
2906 sa = ++nw;
2907 while (*nw != ')') {
2908 if (!*nw) {
2909 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2910 file, linenum, args[0], cw);
2911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
2914 nw++;
2915 }
2916 *nw = '\0';
2917 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002918 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002919 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002920 if (*nw)
2921 *nw++ = '\0';
2922 type = stktable_get_data_type(cw);
2923 if (type < 0) {
2924 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2925 file, linenum, args[0], cw);
2926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
Willy Tarreauac782882010-06-20 10:41:54 +02002929
2930 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2931 switch (err) {
2932 case PE_NONE: break;
2933 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002934 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2935 file, linenum, args[0], cw);
2936 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002937 break;
2938
2939 case PE_ARG_MISSING:
2940 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2941 file, linenum, args[0], cw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944
2945 case PE_ARG_NOT_USED:
2946 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2947 file, linenum, args[0], cw);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950
2951 default:
2952 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2953 file, linenum, args[0], cw);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002956 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002957 }
2958 myidx++;
2959 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002960 else {
2961 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2962 file, linenum, args[myidx]);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002965 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002966 }
2967
2968 if (!curproxy->table.size) {
2969 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2970 file, linenum);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974
2975 if (curproxy->table.type == (unsigned int)-1) {
2976 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2977 file, linenum);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981 }
2982 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002983 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002984 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002985 int myidx = 0;
2986 const char *name = NULL;
2987 int flags;
2988
2989 if (curproxy == &defproxy) {
2990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
2995 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2996 err_code |= ERR_WARN;
2997 goto out;
2998 }
2999
3000 myidx++;
3001 if ((strcmp(args[myidx], "store") == 0) ||
3002 (strcmp(args[myidx], "store-request") == 0)) {
3003 myidx++;
3004 flags = STK_IS_STORE;
3005 }
3006 else if (strcmp(args[myidx], "store-response") == 0) {
3007 myidx++;
3008 flags = STK_IS_STORE | STK_ON_RSP;
3009 }
3010 else if (strcmp(args[myidx], "match") == 0) {
3011 myidx++;
3012 flags = STK_IS_MATCH;
3013 }
3014 else if (strcmp(args[myidx], "on") == 0) {
3015 myidx++;
3016 flags = STK_IS_MATCH | STK_IS_STORE;
3017 }
3018 else {
3019 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
3024 if (*(args[myidx]) == 0) {
3025 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029
David du Colombier7af46052012-05-16 14:16:48 +02003030 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003031 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003032 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
3036
3037 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003038 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3040 file, linenum, args[0], expr->fetch->kw);
3041 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003042 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 goto out;
3044 }
3045 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003046 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3048 file, linenum, args[0], expr->fetch->kw);
3049 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003050 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003051 goto out;
3052 }
3053 }
3054
3055 if (strcmp(args[myidx], "table") == 0) {
3056 myidx++;
3057 name = args[myidx++];
3058 }
3059
Willy Tarreauef6494c2010-01-28 17:12:36 +01003060 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003061 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3062 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3063 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003064 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003065 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 goto out;
3067 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003069 else if (*(args[myidx])) {
3070 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3071 file, linenum, args[0], args[myidx]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003073 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003074 goto out;
3075 }
Emeric Brun97679e72010-09-23 17:56:44 +02003076 if (flags & STK_ON_RSP)
3077 err_code |= warnif_cond_requires_req(cond, file, linenum);
3078 else
3079 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003080
Emeric Brunb982a3d2010-01-04 15:45:53 +01003081 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3082 rule->cond = cond;
3083 rule->expr = expr;
3084 rule->flags = flags;
3085 rule->table.name = name ? strdup(name) : NULL;
3086 LIST_INIT(&rule->list);
3087 if (flags & STK_ON_RSP)
3088 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3089 else
3090 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003095
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3097 curproxy->uri_auth = NULL; /* we must detach from the default config */
3098
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003099 if (!*args[1]) {
3100 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003101 } else if (!strcmp(args[1], "admin")) {
3102 struct stats_admin_rule *rule;
3103
3104 if (curproxy == &defproxy) {
3105 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
3108 }
3109
3110 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3111 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3112 err_code |= ERR_ALERT | ERR_ABORT;
3113 goto out;
3114 }
3115
3116 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3117 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3118 file, linenum, args[0], args[1]);
3119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003122 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3123 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3124 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128
3129 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3130
3131 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3132 rule->cond = cond;
3133 LIST_INIT(&rule->list);
3134 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 } else if (!strcmp(args[1], "uri")) {
3136 if (*(args[2]) == 0) {
3137 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3141 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_ABORT;
3143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 }
3145 } else if (!strcmp(args[1], "realm")) {
3146 if (*(args[2]) == 0) {
3147 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3151 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_ABORT;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003155 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003156 unsigned interval;
3157
3158 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3159 if (err) {
3160 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3161 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003164 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3165 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_ABORT;
3167 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003168 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003169 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003170 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003171
3172 if (curproxy == &defproxy) {
3173 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177
3178 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3179 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3180 err_code |= ERR_ALERT | ERR_ABORT;
3181 goto out;
3182 }
3183
Willy Tarreauff011f22011-01-06 17:51:27 +01003184 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3185 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003186 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3187 file, linenum, args[0]);
3188 err_code |= ERR_WARN;
3189 }
3190
Willy Tarreauff011f22011-01-06 17:51:27 +01003191 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003192
Willy Tarreauff011f22011-01-06 17:51:27 +01003193 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003194 err_code |= ERR_ALERT | ERR_ABORT;
3195 goto out;
3196 }
3197
Willy Tarreauff011f22011-01-06 17:51:27 +01003198 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3199 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003200
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 } else if (!strcmp(args[1], "auth")) {
3202 if (*(args[2]) == 0) {
3203 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3207 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_ABORT;
3209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211 } else if (!strcmp(args[1], "scope")) {
3212 if (*(args[2]) == 0) {
3213 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_ABORT;
3219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 }
3221 } else if (!strcmp(args[1], "enable")) {
3222 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_ABORT;
3225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003227 } else if (!strcmp(args[1], "hide-version")) {
3228 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3229 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_ABORT;
3231 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003232 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003233 } else if (!strcmp(args[1], "show-legends")) {
3234 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3235 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3236 err_code |= ERR_ALERT | ERR_ABORT;
3237 goto out;
3238 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003239 } else if (!strcmp(args[1], "show-node")) {
3240
3241 if (*args[2]) {
3242 int i;
3243 char c;
3244
3245 for (i=0; args[2][i]; i++) {
3246 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003247 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3248 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003249 break;
3250 }
3251
3252 if (!i || args[2][i]) {
3253 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3254 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3255 file, linenum, args[0], args[1]);
3256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
3258 }
3259 }
3260
3261 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3262 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3263 err_code |= ERR_ALERT | ERR_ABORT;
3264 goto out;
3265 }
3266 } else if (!strcmp(args[1], "show-desc")) {
3267 char *desc = NULL;
3268
3269 if (*args[2]) {
3270 int i, len=0;
3271 char *d;
3272
3273 for(i=2; *args[i]; i++)
3274 len += strlen(args[i])+1;
3275
3276 desc = d = (char *)calloc(1, len);
3277
3278 d += sprintf(d, "%s", args[2]);
3279 for(i=3; *args[i]; i++)
3280 d += sprintf(d, " %s", args[i]);
3281 }
3282
3283 if (!*args[2] && !global.desc)
3284 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3285 file, linenum, args[1]);
3286 else {
3287 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3288 free(desc);
3289 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3290 err_code |= ERR_ALERT | ERR_ABORT;
3291 goto out;
3292 }
3293 free(desc);
3294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003296stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003297 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 +01003298 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
3302 }
3303 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003304 int optnum;
3305
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003306 if (*(args[1]) == '\0') {
3307 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3308 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003312
3313 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3314 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003315 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3316 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3317 file, linenum, cfg_opts[optnum].name);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
Willy Tarreau93893792009-07-23 13:19:11 +02003321 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3322 err_code |= ERR_WARN;
3323 goto out;
3324 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003325
Willy Tarreau3842f002009-06-14 11:39:52 +02003326 curproxy->no_options &= ~cfg_opts[optnum].val;
3327 curproxy->options &= ~cfg_opts[optnum].val;
3328
3329 switch (kwm) {
3330 case KWM_STD:
3331 curproxy->options |= cfg_opts[optnum].val;
3332 break;
3333 case KWM_NO:
3334 curproxy->no_options |= cfg_opts[optnum].val;
3335 break;
3336 case KWM_DEF: /* already cleared */
3337 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003338 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003339
Willy Tarreau93893792009-07-23 13:19:11 +02003340 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003341 }
3342 }
3343
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003344 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3345 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003346 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3347 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3348 file, linenum, cfg_opts2[optnum].name);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
Willy Tarreau93893792009-07-23 13:19:11 +02003352 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3353 err_code |= ERR_WARN;
3354 goto out;
3355 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003356
Willy Tarreau3842f002009-06-14 11:39:52 +02003357 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3358 curproxy->options2 &= ~cfg_opts2[optnum].val;
3359
3360 switch (kwm) {
3361 case KWM_STD:
3362 curproxy->options2 |= cfg_opts2[optnum].val;
3363 break;
3364 case KWM_NO:
3365 curproxy->no_options2 |= cfg_opts2[optnum].val;
3366 break;
3367 case KWM_DEF: /* already cleared */
3368 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003369 }
Willy Tarreau93893792009-07-23 13:19:11 +02003370 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003371 }
3372 }
3373
Willy Tarreau3842f002009-06-14 11:39:52 +02003374 if (kwm != KWM_STD) {
3375 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003376 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003379 }
3380
Emeric Brun3a058f32009-06-30 18:26:00 +02003381 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003382 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003384 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003385 if (*(args[2]) != '\0') {
3386 if (!strcmp(args[2], "clf")) {
3387 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003388 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003389 } else {
3390 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003393 }
3394 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003395 if (curproxy->logformat_string != default_http_log_format &&
3396 curproxy->logformat_string != default_tcp_log_format &&
3397 curproxy->logformat_string != clf_http_log_format)
3398 free(curproxy->logformat_string);
3399 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003400 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003401 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003403 if (curproxy->logformat_string != default_http_log_format &&
3404 curproxy->logformat_string != default_tcp_log_format &&
3405 curproxy->logformat_string != clf_http_log_format)
3406 free(curproxy->logformat_string);
3407 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 else if (!strcmp(args[1], "tcpka")) {
3410 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003411 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003413
3414 if (curproxy->cap & PR_CAP_FE)
3415 curproxy->options |= PR_O_TCP_CLI_KA;
3416 if (curproxy->cap & PR_CAP_BE)
3417 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
3419 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003420 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_WARN;
3422
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003424 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003425 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003426 curproxy->options2 &= ~PR_O2_CHK_ANY;
3427 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 if (!*args[2]) { /* no argument */
3429 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3430 curproxy->check_len = strlen(DEF_CHECK_REQ);
3431 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003432 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 curproxy->check_req = (char *)malloc(reqlen);
3434 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003435 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003437 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 if (*args[4])
3439 reqlen += strlen(args[4]);
3440 else
3441 reqlen += strlen("HTTP/1.0");
3442
3443 curproxy->check_req = (char *)malloc(reqlen);
3444 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003445 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003446 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003447 }
3448 else if (!strcmp(args[1], "ssl-hello-chk")) {
3449 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003450 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003452
Willy Tarreaua534fea2008-08-03 12:19:50 +02003453 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003454 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003455 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003456 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 }
Willy Tarreau23677902007-05-08 23:50:35 +02003458 else if (!strcmp(args[1], "smtpchk")) {
3459 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003460 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003461 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003462 curproxy->options2 &= ~PR_O2_CHK_ANY;
3463 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003464
3465 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3466 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3467 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3468 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3469 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3470 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3471 curproxy->check_req = (char *)malloc(reqlen);
3472 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3473 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3474 } else {
3475 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3476 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3477 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3478 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3479 }
3480 }
3481 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003482 else if (!strcmp(args[1], "pgsql-check")) {
3483 /* use PostgreSQL request to check servers' health */
3484 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3485 err_code |= ERR_WARN;
3486
3487 free(curproxy->check_req);
3488 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003489 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003490 curproxy->options2 |= PR_O2_PGSQL_CHK;
3491
3492 if (*(args[2])) {
3493 int cur_arg = 2;
3494
3495 while (*(args[cur_arg])) {
3496 if (strcmp(args[cur_arg], "user") == 0) {
3497 char * packet;
3498 uint32_t packet_len;
3499 uint32_t pv;
3500
3501 /* suboption header - needs additional argument for it */
3502 if (*(args[cur_arg+1]) == 0) {
3503 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3504 file, linenum, args[0], args[1], args[cur_arg]);
3505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
3507 }
3508
3509 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3510 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3511 pv = htonl(0x30000); /* protocol version 3.0 */
3512
3513 packet = (char*) calloc(1, packet_len);
3514
3515 memcpy(packet + 4, &pv, 4);
3516
3517 /* copy "user" */
3518 memcpy(packet + 8, "user", 4);
3519
3520 /* copy username */
3521 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3522
3523 free(curproxy->check_req);
3524 curproxy->check_req = packet;
3525 curproxy->check_len = packet_len;
3526
3527 packet_len = htonl(packet_len);
3528 memcpy(packet, &packet_len, 4);
3529 cur_arg += 2;
3530 } else {
3531 /* unknown suboption - catchall */
3532 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3533 file, linenum, args[0], args[1]);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
3537 } /* end while loop */
3538 }
3539 }
3540
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003541 else if (!strcmp(args[1], "redis-check")) {
3542 /* use REDIS PING request to check servers' health */
3543 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3544 err_code |= ERR_WARN;
3545
3546 free(curproxy->check_req);
3547 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003548 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003549 curproxy->options2 |= PR_O2_REDIS_CHK;
3550
3551 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3552 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3553 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3554 }
3555
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003556 else if (!strcmp(args[1], "mysql-check")) {
3557 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003558 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3559 err_code |= ERR_WARN;
3560
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003561 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003562 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003563 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003564 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003565
3566 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3567 * const char mysql40_client_auth_pkt[] = {
3568 * "\x0e\x00\x00" // packet length
3569 * "\x01" // packet number
3570 * "\x00\x00" // client capabilities
3571 * "\x00\x00\x01" // max packet
3572 * "haproxy\x00" // username (null terminated string)
3573 * "\x00" // filler (always 0x00)
3574 * "\x01\x00\x00" // packet length
3575 * "\x00" // packet number
3576 * "\x01" // COM_QUIT command
3577 * };
3578 */
3579
3580 if (*(args[2])) {
3581 int cur_arg = 2;
3582
3583 while (*(args[cur_arg])) {
3584 if (strcmp(args[cur_arg], "user") == 0) {
3585 char *mysqluser;
3586 int packetlen, reqlen, userlen;
3587
3588 /* suboption header - needs additional argument for it */
3589 if (*(args[cur_arg+1]) == 0) {
3590 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3591 file, linenum, args[0], args[1], args[cur_arg]);
3592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
3594 }
3595 mysqluser = args[cur_arg + 1];
3596 userlen = strlen(mysqluser);
3597 packetlen = userlen + 7;
3598 reqlen = packetlen + 9;
3599
3600 free(curproxy->check_req);
3601 curproxy->check_req = (char *)calloc(1, reqlen);
3602 curproxy->check_len = reqlen;
3603
3604 snprintf(curproxy->check_req, 4, "%c%c%c",
3605 ((unsigned char) packetlen & 0xff),
3606 ((unsigned char) (packetlen >> 8) & 0xff),
3607 ((unsigned char) (packetlen >> 16) & 0xff));
3608
3609 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003610 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003611 curproxy->check_req[8] = 1;
3612 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3613 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3614 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3615 cur_arg += 2;
3616 } else {
3617 /* unknown suboption - catchall */
3618 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3619 file, linenum, args[0], args[1]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623 } /* end while loop */
3624 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003625 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003626 else if (!strcmp(args[1], "ldap-check")) {
3627 /* use LDAP request to check servers' health */
3628 free(curproxy->check_req);
3629 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003630 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003631 curproxy->options2 |= PR_O2_LDAP_CHK;
3632
3633 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3634 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3635 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3636 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003637 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003638 int cur_arg;
3639
3640 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3641 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003642 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003643
Willy Tarreau87cf5142011-08-19 22:57:24 +02003644 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003645
3646 free(curproxy->fwdfor_hdr_name);
3647 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3648 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3649
3650 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3651 cur_arg = 2;
3652 while (*(args[cur_arg])) {
3653 if (!strcmp(args[cur_arg], "except")) {
3654 /* suboption except - needs additional argument for it */
3655 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3656 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3657 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003660 }
3661 /* flush useless bits */
3662 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003663 cur_arg += 2;
3664 } else if (!strcmp(args[cur_arg], "header")) {
3665 /* suboption header - needs additional argument for it */
3666 if (*(args[cur_arg+1]) == 0) {
3667 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3668 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003671 }
3672 free(curproxy->fwdfor_hdr_name);
3673 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3674 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3675 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003676 } else if (!strcmp(args[cur_arg], "if-none")) {
3677 curproxy->options &= ~PR_O_FF_ALWAYS;
3678 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003679 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003680 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003681 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003682 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003685 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003686 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003687 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003688 else if (!strcmp(args[1], "originalto")) {
3689 int cur_arg;
3690
3691 /* insert x-original-to field, but not for the IP address listed as an except.
3692 * set default options (ie: bitfield, header name, etc)
3693 */
3694
3695 curproxy->options |= PR_O_ORGTO;
3696
3697 free(curproxy->orgto_hdr_name);
3698 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3699 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3700
Willy Tarreau87cf5142011-08-19 22:57:24 +02003701 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003702 cur_arg = 2;
3703 while (*(args[cur_arg])) {
3704 if (!strcmp(args[cur_arg], "except")) {
3705 /* suboption except - needs additional argument for it */
3706 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3707 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3708 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003711 }
3712 /* flush useless bits */
3713 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3714 cur_arg += 2;
3715 } else if (!strcmp(args[cur_arg], "header")) {
3716 /* suboption header - needs additional argument for it */
3717 if (*(args[cur_arg+1]) == 0) {
3718 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3719 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003722 }
3723 free(curproxy->orgto_hdr_name);
3724 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3725 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3726 cur_arg += 2;
3727 } else {
3728 /* unknown suboption - catchall */
3729 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3730 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003733 }
3734 } /* end while loop */
3735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 else {
3737 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 }
Willy Tarreau93893792009-07-23 13:19:11 +02003741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003743 else if (!strcmp(args[0], "default_backend")) {
3744 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003746
3747 if (*(args[1]) == 0) {
3748 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003751 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003752 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003753 curproxy->defbe.name = strdup(args[1]);
3754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003758
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003759 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3760 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 /* enable reconnections to dispatch */
3763 curproxy->options |= PR_O_REDISP;
3764 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003765 else if (!strcmp(args[0], "http-check")) {
3766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003768
3769 if (strcmp(args[1], "disable-on-404") == 0) {
3770 /* enable a graceful server shutdown on an HTTP 404 response */
3771 curproxy->options |= PR_O_DISABLE404;
3772 }
Willy Tarreauef781042010-01-27 11:53:01 +01003773 else if (strcmp(args[1], "send-state") == 0) {
3774 /* enable emission of the apparent state of a server in HTTP checks */
3775 curproxy->options2 |= PR_O2_CHK_SNDST;
3776 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003777 else if (strcmp(args[1], "expect") == 0) {
3778 const char *ptr_arg;
3779 int cur_arg;
3780
3781 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3782 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
3785 }
3786
3787 cur_arg = 2;
3788 /* consider exclamation marks, sole or at the beginning of a word */
3789 while (*(ptr_arg = args[cur_arg])) {
3790 while (*ptr_arg == '!') {
3791 curproxy->options2 ^= PR_O2_EXP_INV;
3792 ptr_arg++;
3793 }
3794 if (*ptr_arg)
3795 break;
3796 cur_arg++;
3797 }
3798 /* now ptr_arg points to the beginning of a word past any possible
3799 * exclamation mark, and cur_arg is the argument which holds this word.
3800 */
3801 if (strcmp(ptr_arg, "status") == 0) {
3802 if (!*(args[cur_arg + 1])) {
3803 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3804 file, linenum, args[0], args[1], ptr_arg);
3805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
3807 }
3808 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003809 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003810 curproxy->expect_str = strdup(args[cur_arg + 1]);
3811 }
3812 else if (strcmp(ptr_arg, "string") == 0) {
3813 if (!*(args[cur_arg + 1])) {
3814 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3815 file, linenum, args[0], args[1], ptr_arg);
3816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
3818 }
3819 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003820 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003821 curproxy->expect_str = strdup(args[cur_arg + 1]);
3822 }
3823 else if (strcmp(ptr_arg, "rstatus") == 0) {
3824 if (!*(args[cur_arg + 1])) {
3825 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3826 file, linenum, args[0], args[1], ptr_arg);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003831 free(curproxy->expect_str);
3832 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3833 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003834 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3835 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3836 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3837 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840 }
3841 }
3842 else if (strcmp(ptr_arg, "rstring") == 0) {
3843 if (!*(args[cur_arg + 1])) {
3844 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3845 file, linenum, args[0], args[1], ptr_arg);
3846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
3849 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003850 free(curproxy->expect_str);
3851 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3852 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003853 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3854 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3855 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3856 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
3859 }
3860 }
3861 else {
3862 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3863 file, linenum, args[0], args[1], ptr_arg);
3864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
3866 }
3867 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003868 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003869 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 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003872 }
3873 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003874 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003875 if (curproxy == &defproxy) {
3876 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003879 }
3880
Willy Tarreaub80c2302007-11-30 20:51:32 +01003881 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003883
3884 if (strcmp(args[1], "fail") == 0) {
3885 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003886 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003887 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3888 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003891 }
3892
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003893 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3894 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3895 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003898 }
3899 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3900 }
3901 else {
3902 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003905 }
3906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907#ifdef TPROXY
3908 else if (!strcmp(args[0], "transparent")) {
3909 /* enable transparent proxy connections */
3910 curproxy->options |= PR_O_TRANSP;
3911 }
3912#endif
3913 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003914 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003916
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 if (*(args[1]) == 0) {
3918 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 }
3922 curproxy->maxconn = atol(args[1]);
3923 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003924 else if (!strcmp(args[0], "backlog")) { /* backlog */
3925 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003927
3928 if (*(args[1]) == 0) {
3929 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003932 }
3933 curproxy->backlog = atol(args[1]);
3934 }
Willy Tarreau86034312006-12-29 00:10:33 +01003935 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003936 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003938
Willy Tarreau86034312006-12-29 00:10:33 +01003939 if (*(args[1]) == 0) {
3940 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003943 }
3944 curproxy->fullconn = atol(args[1]);
3945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3947 if (*(args[1]) == 0) {
3948 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003952 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3953 if (err) {
3954 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3955 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003958 }
3959 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
3961 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003962 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 if (curproxy == &defproxy) {
3964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003968 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003970
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 if (strchr(args[1], ':') == NULL) {
3972 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003976 sk = str2sa(args[1]);
3977 if (!sk) {
3978 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
3982 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003983 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984 }
3985 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003988
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003989 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3990 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003995 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3996 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3997 err_code |= ERR_WARN;
3998
3999 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4000 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4001 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4002 }
4003 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4004 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4005 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4006 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004007 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4008 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4009 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4010 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004011 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004012 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
4016 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004017 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004019 char *rport, *raddr;
4020 short realport = 0;
4021 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004023 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004028 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004029 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030
4031 if (!*args[2]) {
4032 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004037
4038 err = invalid_char(args[1]);
4039 if (err) {
4040 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4041 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004044 }
4045
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004046 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004047 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004048
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004049 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4051 err_code |= ERR_ALERT | ERR_ABORT;
4052 goto out;
4053 }
4054
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004055 /* the servers are linked backwards first */
4056 newsrv->next = curproxy->srv;
4057 curproxy->srv = newsrv;
4058 newsrv->proxy = curproxy;
4059 newsrv->conf.file = file;
4060 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061
Simon Hormanaf514952011-06-21 14:34:57 +09004062 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063 LIST_INIT(&newsrv->pendconns);
4064 do_check = 0;
4065 newsrv->state = SRV_RUNNING; /* early server setup */
4066 newsrv->last_change = now.tv_sec;
4067 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004069 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004070 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004071 * - IP: => port=+0, relative
4072 * - IP:N => port=N, absolute
4073 * - IP:+N => port=+N, relative
4074 * - IP:-N => port=-N, relative
4075 */
4076 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004077 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004078 if (rport) {
4079 *rport++ = 0;
4080 realport = atol(rport);
4081 if (!isdigit((unsigned char)*rport))
4082 newsrv->state |= SRV_MAPPORTS;
4083 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004084 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004085
Willy Tarreaufab5a432011-03-04 15:31:53 +01004086 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004087 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004088 if (!sk) {
4089 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004094 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02004095 newsrv->sock = &sock_raw;
4096 newsrv->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004097
4098 if (!sk) {
4099 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4100 file, linenum, newsrv->addr.ss_family, args[2]);
4101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
4103 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004104 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004105
4106 newsrv->check_port = curproxy->defsrv.check_port;
4107 newsrv->inter = curproxy->defsrv.inter;
4108 newsrv->fastinter = curproxy->defsrv.fastinter;
4109 newsrv->downinter = curproxy->defsrv.downinter;
4110 newsrv->rise = curproxy->defsrv.rise;
4111 newsrv->fall = curproxy->defsrv.fall;
4112 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4113 newsrv->minconn = curproxy->defsrv.minconn;
4114 newsrv->maxconn = curproxy->defsrv.maxconn;
4115 newsrv->slowstart = curproxy->defsrv.slowstart;
4116 newsrv->onerror = curproxy->defsrv.onerror;
4117 newsrv->consecutive_errors_limit
4118 = curproxy->defsrv.consecutive_errors_limit;
4119 newsrv->uweight = newsrv->iweight
4120 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004122 newsrv->curfd = -1; /* no health-check in progress */
4123 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004124
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004125 cur_arg = 3;
4126 } else {
4127 newsrv = &curproxy->defsrv;
4128 cur_arg = 1;
4129 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004130
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004132 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004133 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004134
4135 if (!*args[cur_arg + 1]) {
4136 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4137 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004140 }
4141
4142 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004143 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004144
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004145 if (newsrv->puid <= 0) {
4146 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004147 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004150 }
4151
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004152 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4153 if (node) {
4154 struct server *target = container_of(node, struct server, conf.id);
4155 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4156 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
4160 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004161 cur_arg += 2;
4162 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004163 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 newsrv->cookie = strdup(args[cur_arg + 1]);
4165 newsrv->cklen = strlen(args[cur_arg + 1]);
4166 cur_arg += 2;
4167 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004168 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004169 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4170 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4171 cur_arg += 2;
4172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004174 if (!*args[cur_arg + 1]) {
4175 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4176 file, linenum, args[cur_arg]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
4180
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004182 if (newsrv->rise <= 0) {
4183 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4184 file, linenum, args[cur_arg]);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188
Willy Tarreau96839092010-03-29 10:02:24 +02004189 if (newsrv->health)
4190 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004191 cur_arg += 2;
4192 }
4193 else if (!strcmp(args[cur_arg], "fall")) {
4194 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004195
4196 if (!*args[cur_arg + 1]) {
4197 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4198 file, linenum, args[cur_arg]);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
4202
4203 if (newsrv->fall <= 0) {
4204 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4205 file, linenum, args[cur_arg]);
4206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
4208 }
4209
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 cur_arg += 2;
4211 }
4212 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004213 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4214 if (err) {
4215 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4216 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004219 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004220 if (val <= 0) {
4221 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4222 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004225 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004226 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 cur_arg += 2;
4228 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004229 else if (!strcmp(args[cur_arg], "fastinter")) {
4230 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4231 if (err) {
4232 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4233 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004236 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004237 if (val <= 0) {
4238 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4239 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004242 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004243 newsrv->fastinter = val;
4244 cur_arg += 2;
4245 }
4246 else if (!strcmp(args[cur_arg], "downinter")) {
4247 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4248 if (err) {
4249 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4250 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004253 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004254 if (val <= 0) {
4255 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4256 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004259 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004260 newsrv->downinter = val;
4261 cur_arg += 2;
4262 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004263 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004264 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004265 if (!sk) {
4266 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004271 cur_arg += 2;
4272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 else if (!strcmp(args[cur_arg], "port")) {
4274 newsrv->check_port = atol(args[cur_arg + 1]);
4275 cur_arg += 2;
4276 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004277 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 newsrv->state |= SRV_BACKUP;
4279 cur_arg ++;
4280 }
Simon Hormanfa461682011-06-25 09:39:49 +09004281 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4282 newsrv->state |= SRV_NON_STICK;
4283 cur_arg ++;
4284 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004285 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4286 newsrv->state |= SRV_SEND_PROXY;
4287 cur_arg ++;
4288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289 else if (!strcmp(args[cur_arg], "weight")) {
4290 int w;
4291 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004292 if (w < 0 || w > 256) {
4293 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004298 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004299 cur_arg += 2;
4300 }
4301 else if (!strcmp(args[cur_arg], "minconn")) {
4302 newsrv->minconn = atol(args[cur_arg + 1]);
4303 cur_arg += 2;
4304 }
4305 else if (!strcmp(args[cur_arg], "maxconn")) {
4306 newsrv->maxconn = atol(args[cur_arg + 1]);
4307 cur_arg += 2;
4308 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004309 else if (!strcmp(args[cur_arg], "maxqueue")) {
4310 newsrv->maxqueue = atol(args[cur_arg + 1]);
4311 cur_arg += 2;
4312 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004313 else if (!strcmp(args[cur_arg], "slowstart")) {
4314 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004315 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004316 if (err) {
4317 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4318 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004321 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004322 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004323 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4324 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004327 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004328 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004329 cur_arg += 2;
4330 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004331 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004332
4333 if (!*args[cur_arg + 1]) {
4334 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4335 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004338 }
4339
4340 newsrv->trackit = strdup(args[cur_arg + 1]);
4341
4342 cur_arg += 2;
4343 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004344 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 global.maxsock++;
4346 do_check = 1;
4347 cur_arg += 1;
4348 }
Willy Tarreau96839092010-03-29 10:02:24 +02004349 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4350 newsrv->state |= SRV_MAINTAIN;
4351 newsrv->state &= ~SRV_RUNNING;
4352 newsrv->health = 0;
4353 cur_arg += 1;
4354 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004355 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004356 if (!strcmp(args[cur_arg + 1], "none"))
4357 newsrv->observe = HANA_OBS_NONE;
4358 else if (!strcmp(args[cur_arg + 1], "layer4"))
4359 newsrv->observe = HANA_OBS_LAYER4;
4360 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4361 if (curproxy->mode != PR_MODE_HTTP) {
4362 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4363 file, linenum, args[cur_arg + 1]);
4364 err_code |= ERR_ALERT;
4365 }
4366 newsrv->observe = HANA_OBS_LAYER7;
4367 }
4368 else {
4369 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004370 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004371 file, linenum, args[cur_arg], args[cur_arg + 1]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375
4376 cur_arg += 2;
4377 }
4378 else if (!strcmp(args[cur_arg], "on-error")) {
4379 if (!strcmp(args[cur_arg + 1], "fastinter"))
4380 newsrv->onerror = HANA_ONERR_FASTINTER;
4381 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4382 newsrv->onerror = HANA_ONERR_FAILCHK;
4383 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4384 newsrv->onerror = HANA_ONERR_SUDDTH;
4385 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4386 newsrv->onerror = HANA_ONERR_MARKDWN;
4387 else {
4388 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004389 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004390 file, linenum, args[cur_arg], args[cur_arg + 1]);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
4394
4395 cur_arg += 2;
4396 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004397 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4398 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4399 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4400 else {
4401 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4402 file, linenum, args[cur_arg], args[cur_arg + 1]);
4403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
4405 }
4406
4407 cur_arg += 2;
4408 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004409 else if (!strcmp(args[cur_arg], "error-limit")) {
4410 if (!*args[cur_arg + 1]) {
4411 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4412 file, linenum, args[cur_arg]);
4413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
4415 }
4416
4417 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4418
4419 if (newsrv->consecutive_errors_limit <= 0) {
4420 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4421 file, linenum, args[cur_arg]);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004425 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004426 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004427 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004428 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004429 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004430
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004432#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004433 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004434 file, linenum, "source", "usesrc");
4435#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004436 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004438#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 }
4442 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004443 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4444 if (!sk) {
4445 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
4448 }
4449 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004450
4451 if (port_low != port_high) {
4452 int i;
4453 if (port_low <= 0 || port_low > 65535 ||
4454 port_high <= 0 || port_high > 65535 ||
4455 port_low > port_high) {
4456 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4457 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004460 }
4461 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4462 for (i = 0; i < newsrv->sport_range->size; i++)
4463 newsrv->sport_range->ports[i] = port_low + i;
4464 }
4465
Willy Tarreaubaaee002006-06-26 02:48:02 +02004466 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004467 while (*(args[cur_arg])) {
4468 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004469#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4470#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004471 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4472 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4473 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004476 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004477#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004478 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004479 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004480 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004483 }
4484 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004485 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004486 newsrv->state |= SRV_TPROXY_CLI;
4487 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004488 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004489 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004490 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4491 char *name, *end;
4492
4493 name = args[cur_arg+1] + 7;
4494 while (isspace(*name))
4495 name++;
4496
4497 end = name;
4498 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4499 end++;
4500
4501 newsrv->state &= ~SRV_TPROXY_MASK;
4502 newsrv->state |= SRV_TPROXY_DYN;
4503 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4504 newsrv->bind_hdr_len = end - name;
4505 memcpy(newsrv->bind_hdr_name, name, end - name);
4506 newsrv->bind_hdr_name[end-name] = '\0';
4507 newsrv->bind_hdr_occ = -1;
4508
4509 /* now look for an occurrence number */
4510 while (isspace(*end))
4511 end++;
4512 if (*end == ',') {
4513 end++;
4514 name = end;
4515 if (*end == '-')
4516 end++;
4517 while (isdigit(*end))
4518 end++;
4519 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4520 }
4521
4522 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4523 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4524 " occurrences values smaller than %d.\n",
4525 file, linenum, MAX_HDR_HISTORY);
4526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
4528 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004529 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004530 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004531 if (!sk) {
4532 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4533 err_code |= ERR_ALERT | ERR_FATAL;
4534 goto out;
4535 }
4536 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004537 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004538 }
4539 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004540#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004541 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004542#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004543 cur_arg += 2;
4544 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004545#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004546 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004547 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004550#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4551 } /* "usesrc" */
4552
4553 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4554#ifdef SO_BINDTODEVICE
4555 if (!*args[cur_arg + 1]) {
4556 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004560 }
4561 if (newsrv->iface_name)
4562 free(newsrv->iface_name);
4563
4564 newsrv->iface_name = strdup(args[cur_arg + 1]);
4565 newsrv->iface_len = strlen(newsrv->iface_name);
4566 global.last_checks |= LSTCHK_NETADM;
4567#else
4568 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4569 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004572#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004573 cur_arg += 2;
4574 continue;
4575 }
4576 /* this keyword in not an option of "source" */
4577 break;
4578 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004580 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004581 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4582 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_ALERT | ERR_FATAL;
4584 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004587 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004588 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 +01004589 file, linenum, newsrv->id);
4590 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004591 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 +01004592 file, linenum);
4593
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
4597 }
4598
4599 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004600 if (newsrv->trackit) {
4601 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4602 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004605 }
4606
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004607 /* try to get the port from check_addr if check_port not set */
4608 if (!newsrv->check_port)
4609 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004610
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4612 newsrv->check_port = realport; /* by default */
4613 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004614 /* not yet valid, because no port was set on
4615 * the server either. We'll check if we have
4616 * a known port on the first listener.
4617 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004618 struct listener *l = curproxy->listen;
4619 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4620 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004621 }
4622 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4624 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004628
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004629 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004630 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004631 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4632 err_code |= ERR_ALERT | ERR_ABORT;
4633 goto out;
4634 }
4635
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004636 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 newsrv->state |= SRV_CHECKED;
4638 }
4639
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004640 if (!defsrv) {
4641 if (newsrv->state & SRV_BACKUP)
4642 curproxy->srv_bck++;
4643 else
4644 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004645
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004646 newsrv->prev_state = newsrv->state;
4647 }
William Lallemanda73203e2012-03-12 12:48:57 +01004648 }
4649
4650 else if (strcmp(args[0], "unique-id-format") == 0) {
4651 if (!*(args[1])) {
4652 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
4655 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004656 free(curproxy->uniqueid_format_string);
4657 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004658 }
William Lallemanda73203e2012-03-12 12:48:57 +01004659
4660 else if (strcmp(args[0], "unique-id-header") == 0) {
4661 if (!*(args[1])) {
4662 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
4665 }
4666 free(curproxy->header_unique_id);
4667 curproxy->header_unique_id = strdup(args[1]);
4668 }
4669
William Lallemand723b73a2012-02-08 16:37:49 +01004670 else if (strcmp(args[0], "log-format") == 0) {
4671 if (!*(args[1])) {
4672 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4673 err_code |= ERR_ALERT | ERR_FATAL;
4674 goto out;
4675 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004676
4677 if (curproxy->logformat_string != default_http_log_format &&
4678 curproxy->logformat_string != default_tcp_log_format &&
4679 curproxy->logformat_string != clf_http_log_format)
4680 free(curproxy->logformat_string);
4681 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004682 }
William Lallemand723b73a2012-02-08 16:37:49 +01004683
William Lallemand0f99e342011-10-12 17:50:54 +02004684 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4685 /* delete previous herited or defined syslog servers */
4686 struct logsrv *back;
4687
4688 if (*(args[1]) != 0) {
4689 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
4692 }
4693
William Lallemand723b73a2012-02-08 16:37:49 +01004694 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4695 LIST_DEL(&tmplogsrv->list);
4696 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004697 }
4698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004700 struct logsrv *logsrv;
4701
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004703 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004704 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004705 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004706 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004707 LIST_INIT(&node->list);
4708 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 }
4711 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004712
4713 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714
William Lallemand0f99e342011-10-12 17:50:54 +02004715 logsrv->facility = get_log_facility(args[2]);
4716 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 }
4722
William Lallemand0f99e342011-10-12 17:50:54 +02004723 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004725 logsrv->level = get_log_level(args[3]);
4726 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004728 err_code |= ERR_ALERT | ERR_FATAL;
4729 goto out;
4730
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 }
4732 }
4733
William Lallemand0f99e342011-10-12 17:50:54 +02004734 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004735 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004736 logsrv->minlvl = get_log_level(args[4]);
4737 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004738 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
4741
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004742 }
4743 }
4744
Robert Tsai81ae1952007-12-05 10:47:29 +01004745 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004746 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004747 if (!sk) {
4748 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004749 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
4752 }
William Lallemand0f99e342011-10-12 17:50:54 +02004753 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004754 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004755 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004756 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004757 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
4760 }
William Lallemand0f99e342011-10-12 17:50:54 +02004761 logsrv->addr = *sk;
4762 if (!get_host_port(&logsrv->addr))
4763 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
William Lallemand0f99e342011-10-12 17:50:54 +02004765
4766 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
4768 else {
4769 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4770 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
4774 }
4775 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004776 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004777 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004778
Willy Tarreau977b8e42006-12-29 14:19:17 +01004779 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004780 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004781
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004783 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4784 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004788
4789 /* we must first clear any optional default setting */
4790 curproxy->options &= ~PR_O_TPXY_MASK;
4791 free(curproxy->iface_name);
4792 curproxy->iface_name = NULL;
4793 curproxy->iface_len = 0;
4794
Willy Tarreaud5191e72010-02-09 20:50:45 +01004795 sk = str2sa(args[1]);
4796 if (!sk) {
4797 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
4800 }
4801 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004802 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004803
4804 cur_arg = 2;
4805 while (*(args[cur_arg])) {
4806 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004807#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4808#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004809 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4810 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4811 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004814 }
4815#endif
4816 if (!*args[cur_arg + 1]) {
4817 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4818 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004821 }
4822
4823 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004824 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004825 curproxy->options |= PR_O_TPXY_CLI;
4826 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004827 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004828 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004829 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4830 char *name, *end;
4831
4832 name = args[cur_arg+1] + 7;
4833 while (isspace(*name))
4834 name++;
4835
4836 end = name;
4837 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4838 end++;
4839
4840 curproxy->options &= ~PR_O_TPXY_MASK;
4841 curproxy->options |= PR_O_TPXY_DYN;
4842 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4843 curproxy->bind_hdr_len = end - name;
4844 memcpy(curproxy->bind_hdr_name, name, end - name);
4845 curproxy->bind_hdr_name[end-name] = '\0';
4846 curproxy->bind_hdr_occ = -1;
4847
4848 /* now look for an occurrence number */
4849 while (isspace(*end))
4850 end++;
4851 if (*end == ',') {
4852 end++;
4853 name = end;
4854 if (*end == '-')
4855 end++;
4856 while (isdigit(*end))
4857 end++;
4858 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4859 }
4860
4861 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4862 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4863 " occurrences values smaller than %d.\n",
4864 file, linenum, MAX_HDR_HISTORY);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004868 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004869 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004870 if (!sk) {
4871 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
4874 }
4875 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004876 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004877 }
4878 global.last_checks |= LSTCHK_NETADM;
4879#if !defined(CONFIG_HAP_LINUX_TPROXY)
4880 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004881#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004882#else /* no TPROXY support */
4883 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004884 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004887#endif
4888 cur_arg += 2;
4889 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004890 }
4891
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004892 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4893#ifdef SO_BINDTODEVICE
4894 if (!*args[cur_arg + 1]) {
4895 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004899 }
4900 if (curproxy->iface_name)
4901 free(curproxy->iface_name);
4902
4903 curproxy->iface_name = strdup(args[cur_arg + 1]);
4904 curproxy->iface_len = strlen(curproxy->iface_name);
4905 global.last_checks |= LSTCHK_NETADM;
4906#else
4907 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4908 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004911#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004912 cur_arg += 2;
4913 continue;
4914 }
4915 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4916 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004921 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4922 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4923 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934
4935 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004936 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004937 args[0], args[1], args[2], (const char **)args+3);
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], "reqdel")) { /* delete request header from a 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_REMOVE, 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 }
4948 else if (!strcmp(args[0], "reqdeny")) { /* deny 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_DENY, 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 Tarreaubaaee002006-06-26 02:48:02 +02004954 }
4955 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004958 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 }
4962 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004965 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004966 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004969 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004971 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004972 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004974 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004975 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004976 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004978 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
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 Tarreaua496b602006-12-17 23:15:24 +01004982 }
4983 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend 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_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004986 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004988 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4993 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997
4998 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004999 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005000 args[0], args[1], args[2], (const char **)args+3);
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], "reqidel")) { /* delete request header from a 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_REMOVE, 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 }
5011 else if (!strcmp(args[0], "reqideny")) { /* deny 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_DENY, 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 Tarreaubaaee002006-06-26 02:48:02 +02005017 }
5018 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005020 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005021 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
5025 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005027 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005028 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005032 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005034 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005035 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005037 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005040 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005041
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 if (curproxy == &defproxy) {
5043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005047 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 if (*(args[1]) == 0) {
5051 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005055
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005056 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005057 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5058 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5059 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
5062 }
5063 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5064 }
5065 else if (*args[2]) {
5066 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5067 file, linenum, args[0], args[2]);
5068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
5070 }
5071
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005072 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005073 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005074 wl->s = strdup(args[1]);
5075 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005076 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 }
5078 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005079 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005085
Willy Tarreauade5ec42010-01-28 19:33:49 +01005086 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005087 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005088 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005089 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 }
5092 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
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_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005095 args[0], args[1], NULL, (const char **)args+2);
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], "rspdeny")) { /* block response header from a regex */
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_DENY, 0,
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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
5113
Willy Tarreauade5ec42010-01-28 19:33:49 +01005114 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005115 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005116 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 }
5120 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005121 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005122 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005123 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005129 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005130 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
5134 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005135 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005136
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 if (curproxy == &defproxy) {
5138 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005142 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 if (*(args[1]) == 0) {
5146 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
5150
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005151 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005152 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5153 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5154 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
5157 }
5158 err_code |= warnif_cond_requires_req(cond, file, linenum);
5159 }
5160 else if (*args[2]) {
5161 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5162 file, linenum, args[0], args[2]);
5163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
5165 }
5166
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005167 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005168 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005169 wl->s = strdup(args[1]);
5170 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
5172 else if (!strcmp(args[0], "errorloc") ||
5173 !strcmp(args[0], "errorloc302") ||
5174 !strcmp(args[0], "errorloc303")) { /* error location */
5175 int errnum, errlen;
5176 char *err;
5177
Willy Tarreau977b8e42006-12-29 14:19:17 +01005178 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005179 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005180
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005182 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
5186
5187 errnum = atol(args[1]);
5188 if (!strcmp(args[0], "errorloc303")) {
5189 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5190 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5191 } else {
5192 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5193 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5194 }
5195
Willy Tarreau0f772532006-12-23 20:51:41 +01005196 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5197 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005198 chunk_destroy(&curproxy->errmsg[rc]);
5199 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005200 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005203
5204 if (rc >= HTTP_ERR_SIZE) {
5205 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5206 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005207 free(err);
5208 }
5209 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005210 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5211 int errnum, errlen, fd;
5212 char *err;
5213 struct stat stat;
5214
5215 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005217
5218 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005219 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005222 }
5223
5224 fd = open(args[2], O_RDONLY);
5225 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5226 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5227 file, linenum, args[2], args[1]);
5228 if (fd >= 0)
5229 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005232 }
5233
Willy Tarreau27a674e2009-08-17 07:23:33 +02005234 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005235 errlen = stat.st_size;
5236 } else {
5237 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005238 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005239 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005240 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005241 }
5242
5243 err = malloc(errlen); /* malloc() must succeed during parsing */
5244 errnum = read(fd, err, errlen);
5245 if (errnum != errlen) {
5246 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5247 file, linenum, args[2], args[1]);
5248 close(fd);
5249 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005252 }
5253 close(fd);
5254
5255 errnum = atol(args[1]);
5256 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5257 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005258 chunk_destroy(&curproxy->errmsg[rc]);
5259 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005260 break;
5261 }
5262 }
5263
5264 if (rc >= HTTP_ERR_SIZE) {
5265 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5266 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005268 free(err);
5269 }
5270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005272 struct cfg_kw_list *kwl;
5273 int index;
5274
5275 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5276 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5277 if (kwl->kw[index].section != CFG_LISTEN)
5278 continue;
5279 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5280 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005281 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005282 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005283 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005284 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005285 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005288 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005289 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005290 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_WARN;
5292 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005293 }
Willy Tarreau93893792009-07-23 13:19:11 +02005294 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005295 }
5296 }
5297 }
5298
Willy Tarreau6daf3432008-01-22 16:44:08 +01005299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 }
Willy Tarreau93893792009-07-23 13:19:11 +02005303 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005304 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005305 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306}
5307
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005308int
5309cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5310{
5311
5312 int err_code = 0;
5313 const char *err;
5314
5315 if (!strcmp(args[0], "userlist")) { /* new userlist */
5316 struct userlist *newul;
5317
5318 if (!*args[1]) {
5319 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5320 file, linenum, args[0]);
5321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
5323 }
5324
5325 err = invalid_char(args[1]);
5326 if (err) {
5327 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5328 file, linenum, *err, args[0], args[1]);
5329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
5331 }
5332
5333 for (newul = userlist; newul; newul = newul->next)
5334 if (!strcmp(newul->name, args[1])) {
5335 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5336 file, linenum, args[1]);
5337 err_code |= ERR_WARN;
5338 goto out;
5339 }
5340
5341 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5342 if (!newul) {
5343 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5344 err_code |= ERR_ALERT | ERR_ABORT;
5345 goto out;
5346 }
5347
5348 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5349 newul->name = strdup(args[1]);
5350
5351 if (!newul->groupusers | !newul->name) {
5352 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5353 err_code |= ERR_ALERT | ERR_ABORT;
5354 goto out;
5355 }
5356
5357 newul->next = userlist;
5358 userlist = newul;
5359
5360 } else if (!strcmp(args[0], "group")) { /* new group */
5361 int cur_arg, i;
5362 const char *err;
5363
5364 if (!*args[1]) {
5365 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5366 file, linenum, args[0]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370
5371 err = invalid_char(args[1]);
5372 if (err) {
5373 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5374 file, linenum, *err, args[0], args[1]);
5375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
5377 }
5378
5379 for(i = 0; i < userlist->grpcnt; i++)
5380 if (!strcmp(userlist->groups[i], args[1])) {
5381 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5382 file, linenum, args[1], userlist->name);
5383 err_code |= ERR_ALERT;
5384 goto out;
5385 }
5386
5387 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5388 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5389 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
5393
5394 cur_arg = 2;
5395
5396 while (*args[cur_arg]) {
5397 if (!strcmp(args[cur_arg], "users")) {
5398 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5399 cur_arg += 2;
5400 continue;
5401 } else {
5402 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5403 file, linenum, args[0]);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407 }
5408
5409 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5410 } else if (!strcmp(args[0], "user")) { /* new user */
5411 struct auth_users *newuser;
5412 int cur_arg;
5413
5414 if (!*args[1]) {
5415 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5416 file, linenum, args[0]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420
5421 for (newuser = userlist->users; newuser; newuser = newuser->next)
5422 if (!strcmp(newuser->user, args[1])) {
5423 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5424 file, linenum, args[1], userlist->name);
5425 err_code |= ERR_ALERT;
5426 goto out;
5427 }
5428
5429 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5430 if (!newuser) {
5431 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5432 err_code |= ERR_ALERT | ERR_ABORT;
5433 goto out;
5434 }
5435
5436 newuser->user = strdup(args[1]);
5437
5438 newuser->next = userlist->users;
5439 userlist->users = newuser;
5440
5441 cur_arg = 2;
5442
5443 while (*args[cur_arg]) {
5444 if (!strcmp(args[cur_arg], "password")) {
5445#ifndef CONFIG_HAP_CRYPT
5446 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5447 file, linenum);
5448 err_code |= ERR_ALERT;
5449#endif
5450 newuser->pass = strdup(args[cur_arg + 1]);
5451 cur_arg += 2;
5452 continue;
5453 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5454 newuser->pass = strdup(args[cur_arg + 1]);
5455 newuser->flags |= AU_O_INSECURE;
5456 cur_arg += 2;
5457 continue;
5458 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005459 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005460 cur_arg += 2;
5461 continue;
5462 } else {
5463 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5464 file, linenum, args[0]);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
5468 }
5469 } else {
5470 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5471 err_code |= ERR_ALERT | ERR_FATAL;
5472 }
5473
5474out:
5475 return err_code;
5476}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477
5478/*
5479 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005480 * Returns the error code, 0 if OK, or any combination of :
5481 * - ERR_ABORT: must abort ASAP
5482 * - ERR_FATAL: we can continue parsing but not start the service
5483 * - ERR_WARN: a warning has been emitted
5484 * - ERR_ALERT: an alert has been emitted
5485 * Only the two first ones can stop processing, the two others are just
5486 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005488int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005490 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 FILE *f;
5492 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005494 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 if ((f=fopen(file,"r")) == NULL)
5497 return -1;
5498
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005499 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005500 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005501 char *end;
5502 char *args[MAX_LINE_ARGS + 1];
5503 char *line = thisline;
5504
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505 linenum++;
5506
5507 end = line + strlen(line);
5508
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005509 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5510 /* Check if we reached the limit and the last char is not \n.
5511 * Watch out for the last line without the terminating '\n'!
5512 */
5513 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005514 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005515 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005516 }
5517
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005519 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 line++;
5521
5522 arg = 0;
5523 args[arg] = line;
5524
5525 while (*line && arg < MAX_LINE_ARGS) {
5526 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5527 * C equivalent value. Other combinations left unchanged (eg: \1).
5528 */
5529 if (*line == '\\') {
5530 int skip = 0;
5531 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5532 *line = line[1];
5533 skip = 1;
5534 }
5535 else if (line[1] == 'r') {
5536 *line = '\r';
5537 skip = 1;
5538 }
5539 else if (line[1] == 'n') {
5540 *line = '\n';
5541 skip = 1;
5542 }
5543 else if (line[1] == 't') {
5544 *line = '\t';
5545 skip = 1;
5546 }
5547 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005548 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549 unsigned char hex1, hex2;
5550 hex1 = toupper(line[2]) - '0';
5551 hex2 = toupper(line[3]) - '0';
5552 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5553 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5554 *line = (hex1<<4) + hex2;
5555 skip = 3;
5556 }
5557 else {
5558 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005560 }
5561 }
5562 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005563 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 end -= skip;
5565 }
5566 line++;
5567 }
5568 else if (*line == '#' || *line == '\n' || *line == '\r') {
5569 /* end of string, end of loop */
5570 *line = 0;
5571 break;
5572 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005573 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005575 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005576 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 line++;
5578 args[++arg] = line;
5579 }
5580 else {
5581 line++;
5582 }
5583 }
5584
5585 /* empty line */
5586 if (!**args)
5587 continue;
5588
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005589 if (*line) {
5590 /* we had to stop due to too many args.
5591 * Let's terminate the string, print the offending part then cut the
5592 * last arg.
5593 */
5594 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5595 line++;
5596 *line = '\0';
5597
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005598 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005599 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005600 err_code |= ERR_ALERT | ERR_FATAL;
5601 args[arg] = line;
5602 }
5603
Willy Tarreau540abe42007-05-02 20:50:16 +02005604 /* zero out remaining args and ensure that at least one entry
5605 * is zeroed out.
5606 */
5607 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 args[arg] = line;
5609 }
5610
Willy Tarreau3842f002009-06-14 11:39:52 +02005611 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005612 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005613 char *tmp;
5614
Willy Tarreau3842f002009-06-14 11:39:52 +02005615 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005616 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005617 for (arg=0; *args[arg+1]; arg++)
5618 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005619 *tmp = '\0'; // fix the next arg to \0
5620 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005621 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005622 else if (!strcmp(args[0], "default")) {
5623 kwm = KWM_DEF;
5624 for (arg=0; *args[arg+1]; arg++)
5625 args[arg] = args[arg+1]; // shift args after inversion
5626 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005627
William Lallemand0f99e342011-10-12 17:50:54 +02005628 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5629 strcmp(args[0], "log") != 0) {
5630 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005631 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005632 }
5633
Willy Tarreau977b8e42006-12-29 14:19:17 +01005634 if (!strcmp(args[0], "listen") ||
5635 !strcmp(args[0], "frontend") ||
5636 !strcmp(args[0], "backend") ||
5637 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005638 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005640 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005641 cursection = strdup(args[0]);
5642 }
5643 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005645 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005646 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005647 }
5648 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005649 confsect = CFG_USERLIST;
5650 free(cursection);
5651 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005652 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005653 else if (!strcmp(args[0], "peers")) {
5654 confsect = CFG_PEERS;
5655 free(cursection);
5656 cursection = strdup(args[0]);
5657 }
5658
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 /* else it's a section keyword */
5660
5661 switch (confsect) {
5662 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005663 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 break;
5665 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005666 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005668 case CFG_USERLIST:
5669 err_code |= cfg_parse_users(file, linenum, args, kwm);
5670 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005671 case CFG_PEERS:
5672 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5673 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005675 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005678
5679 if (err_code & ERR_ABORT)
5680 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005682 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005683 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005685 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005686}
5687
Willy Tarreaubb925012009-07-23 13:36:36 +02005688/*
5689 * Returns the error code, 0 if OK, or any combination of :
5690 * - ERR_ABORT: must abort ASAP
5691 * - ERR_FATAL: we can continue parsing but not start the service
5692 * - ERR_WARN: a warning has been emitted
5693 * - ERR_ALERT: an alert has been emitted
5694 * Only the two first ones can stop processing, the two others are just
5695 * indicators.
5696 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005697int check_config_validity()
5698{
5699 int cfgerr = 0;
5700 struct proxy *curproxy = NULL;
5701 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005702 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005703 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005704 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705
5706 /*
5707 * Now, check for the integrity of all that we have collected.
5708 */
5709
5710 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005711 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005713 /* first, we will invert the proxy list order */
5714 curproxy = NULL;
5715 while (proxy) {
5716 struct proxy *next;
5717
5718 next = proxy->next;
5719 proxy->next = curproxy;
5720 curproxy = proxy;
5721 if (!next)
5722 break;
5723 proxy = next;
5724 }
5725
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005727 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005728 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005729 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005730 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005731 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005732 unsigned int next_id;
5733
5734 if (!curproxy->uuid) {
5735 /* proxy ID not set, use automatic numbering with first
5736 * spare entry starting with next_pxid.
5737 */
5738 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5739 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5740 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005741 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005742 next_pxid++;
5743
Willy Tarreau55ea7572007-06-17 19:56:27 +02005744
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005746 /* ensure we don't keep listeners uselessly bound */
5747 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 curproxy = curproxy->next;
5749 continue;
5750 }
5751
Willy Tarreauff01a212009-03-15 13:46:16 +01005752 switch (curproxy->mode) {
5753 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005754 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005755 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005756 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5757 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005758 cfgerr++;
5759 }
5760
5761 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005762 Warning("config : servers will be ignored for %s '%s'.\n",
5763 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005764 break;
5765
5766 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005767 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005768 break;
5769
5770 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005771 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005772 break;
5773 }
5774
5775 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005776 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5777 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 cfgerr++;
5779 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005780
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005781 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005782 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005783 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005784 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5785 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005786 cfgerr++;
5787 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005789 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005790 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5791 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005792 cfgerr++;
5793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005795 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005796 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5797 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005798 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005799 }
5800 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005801 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005802 /* If no LB algo is set in a backend, and we're not in
5803 * transparent mode, dispatch mode nor proxy mode, we
5804 * want to use balance roundrobin by default.
5805 */
5806 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5807 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
5809 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005810
Willy Tarreau1620ec32011-08-06 17:05:02 +02005811 if (curproxy->options & PR_O_DISPATCH)
5812 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5813 else if (curproxy->options & PR_O_HTTP_PROXY)
5814 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5815 else if (curproxy->options & PR_O_TRANSP)
5816 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005817
Willy Tarreau1620ec32011-08-06 17:05:02 +02005818 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5819 if (curproxy->options & PR_O_DISABLE404) {
5820 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5821 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5822 err_code |= ERR_WARN;
5823 curproxy->options &= ~PR_O_DISABLE404;
5824 }
5825 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5826 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5827 "send-state", proxy_type_str(curproxy), curproxy->id);
5828 err_code |= ERR_WARN;
5829 curproxy->options &= ~PR_O2_CHK_SNDST;
5830 }
Willy Tarreauef781042010-01-27 11:53:01 +01005831 }
5832
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005833 /* if a default backend was specified, let's find it */
5834 if (curproxy->defbe.name) {
5835 struct proxy *target;
5836
Alex Williams96532db2009-11-01 21:27:13 -05005837 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005838 if (!target) {
5839 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5840 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005841 cfgerr++;
5842 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005843 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5844 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005845 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005846 } else {
5847 free(curproxy->defbe.name);
5848 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005849 /* we force the backend to be present on at least all of
5850 * the frontend's processes.
5851 */
5852 target->bind_proc = curproxy->bind_proc ?
5853 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005854
5855 /* Emit a warning if this proxy also has some servers */
5856 if (curproxy->srv) {
5857 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5858 curproxy->id);
5859 err_code |= ERR_WARN;
5860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861 }
5862 }
5863
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005864 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005865 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5866 /* map jump target for ACT_SETBE in req_rep chain */
5867 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005868 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005869 struct proxy *target;
5870
Willy Tarreaua496b602006-12-17 23:15:24 +01005871 if (exp->action != ACT_SETBE)
5872 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005873
Alex Williams96532db2009-11-01 21:27:13 -05005874 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005875 if (!target) {
5876 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5877 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005878 cfgerr++;
5879 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005880 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5881 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005882 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005883 } else {
5884 free((void *)exp->replace);
5885 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005886 /* we force the backend to be present on at least all of
5887 * the frontend's processes.
5888 */
5889 target->bind_proc = curproxy->bind_proc ?
5890 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005891 }
5892 }
5893 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005894
5895 /* find the target proxy for 'use_backend' rules */
5896 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005897 struct proxy *target;
5898
Alex Williams96532db2009-11-01 21:27:13 -05005899 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005900
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005901 if (!target) {
5902 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5903 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005904 cfgerr++;
5905 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005906 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5907 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005908 cfgerr++;
5909 } else {
5910 free((void *)rule->be.name);
5911 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005912 /* we force the backend to be present on at least all of
5913 * the frontend's processes.
5914 */
5915 target->bind_proc = curproxy->bind_proc ?
5916 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005917 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005918 }
5919
5920 /* find the target proxy for 'use_backend' rules */
5921 list_for_each_entry(srule, &curproxy->server_rules, list) {
5922 struct server *target = findserver(curproxy, srule->srv.name);
5923
5924 if (!target) {
5925 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5926 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5927 cfgerr++;
5928 continue;
5929 }
5930 free((void *)srule->srv.name);
5931 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005932 }
5933
Emeric Brunb982a3d2010-01-04 15:45:53 +01005934 /* find the target table for 'stick' rules */
5935 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5936 struct proxy *target;
5937
Emeric Brun1d33b292010-01-04 15:47:17 +01005938 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5939 if (mrule->flags & STK_IS_STORE)
5940 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5941
Emeric Brunb982a3d2010-01-04 15:45:53 +01005942 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005943 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005944 else
5945 target = curproxy;
5946
5947 if (!target) {
5948 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5949 curproxy->id, mrule->table.name);
5950 cfgerr++;
5951 }
5952 else if (target->table.size == 0) {
5953 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5954 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5955 cfgerr++;
5956 }
Willy Tarreau12785782012-04-27 21:37:17 +02005957 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5958 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005959 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5960 cfgerr++;
5961 }
5962 else {
5963 free((void *)mrule->table.name);
5964 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005965 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005966 }
5967 }
5968
5969 /* find the target table for 'store response' rules */
5970 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5971 struct proxy *target;
5972
Emeric Brun1d33b292010-01-04 15:47:17 +01005973 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5974
Emeric Brunb982a3d2010-01-04 15:45:53 +01005975 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005976 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005977 else
5978 target = curproxy;
5979
5980 if (!target) {
5981 Alert("Proxy '%s': unable to find store table '%s'.\n",
5982 curproxy->id, mrule->table.name);
5983 cfgerr++;
5984 }
5985 else if (target->table.size == 0) {
5986 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5987 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5988 cfgerr++;
5989 }
Willy Tarreau12785782012-04-27 21:37:17 +02005990 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5991 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005992 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5993 cfgerr++;
5994 }
5995 else {
5996 free((void *)mrule->table.name);
5997 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005998 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005999 }
6000 }
6001
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006002 /* find the target table for 'tcp-request' layer 4 rules */
6003 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6004 struct proxy *target;
6005
Willy Tarreau56123282010-08-06 19:06:56 +02006006 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006007 continue;
6008
6009 if (trule->act_prm.trk_ctr.table.n)
6010 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6011 else
6012 target = curproxy;
6013
6014 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006015 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6016 curproxy->id, trule->act_prm.trk_ctr.table.n,
6017 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006018 cfgerr++;
6019 }
6020 else if (target->table.size == 0) {
6021 Alert("Proxy '%s': table '%s' used but not configured.\n",
6022 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6023 cfgerr++;
6024 }
6025 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006026 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 +02006027 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6028 cfgerr++;
6029 }
6030 else {
6031 free(trule->act_prm.trk_ctr.table.n);
6032 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006033 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006034 * to pass a list of counters to track and allocate them right here using
6035 * stktable_alloc_data_type().
6036 */
6037 }
6038 }
6039
Willy Tarreaud1f96522010-08-03 19:34:32 +02006040 /* find the target table for 'tcp-request' layer 6 rules */
6041 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6042 struct proxy *target;
6043
Willy Tarreau56123282010-08-06 19:06:56 +02006044 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006045 continue;
6046
6047 if (trule->act_prm.trk_ctr.table.n)
6048 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6049 else
6050 target = curproxy;
6051
6052 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006053 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6054 curproxy->id, trule->act_prm.trk_ctr.table.n,
6055 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006056 cfgerr++;
6057 }
6058 else if (target->table.size == 0) {
6059 Alert("Proxy '%s': table '%s' used but not configured.\n",
6060 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6061 cfgerr++;
6062 }
6063 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006064 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 +02006065 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6066 cfgerr++;
6067 }
6068 else {
6069 free(trule->act_prm.trk_ctr.table.n);
6070 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006071 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006072 * to pass a list of counters to track and allocate them right here using
6073 * stktable_alloc_data_type().
6074 */
6075 }
6076 }
6077
Emeric Brun32da3c42010-09-23 18:39:19 +02006078 if (curproxy->table.peers.name) {
6079 struct peers *curpeers = peers;
6080
6081 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6082 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6083 free((void *)curproxy->table.peers.name);
6084 curproxy->table.peers.p = peers;
6085 break;
6086 }
6087 }
6088
6089 if (!curpeers) {
6090 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6091 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006092 free((void *)curproxy->table.peers.name);
6093 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006094 cfgerr++;
6095 }
6096 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006097 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6098 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006099 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006100 cfgerr++;
6101 }
6102 }
6103
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006104 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006105 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006106 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6107 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6108 "proxy", curproxy->id);
6109 cfgerr++;
6110 goto out_uri_auth_compat;
6111 }
6112
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006113 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006114 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006115 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006116 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006117
Willy Tarreau95fa4692010-02-01 13:05:50 +01006118 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6119 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006120
6121 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006122 uri_auth_compat_req[i++] = "realm";
6123 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6124 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006125
Willy Tarreau95fa4692010-02-01 13:05:50 +01006126 uri_auth_compat_req[i++] = "unless";
6127 uri_auth_compat_req[i++] = "{";
6128 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6129 uri_auth_compat_req[i++] = "}";
6130 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006131
Willy Tarreauff011f22011-01-06 17:51:27 +01006132 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6133 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006134 cfgerr++;
6135 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006136 }
6137
Willy Tarreauff011f22011-01-06 17:51:27 +01006138 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006139
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006140 if (curproxy->uri_auth->auth_realm) {
6141 free(curproxy->uri_auth->auth_realm);
6142 curproxy->uri_auth->auth_realm = NULL;
6143 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006144
6145 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006146 }
6147out_uri_auth_compat:
6148
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006149 cfgerr += acl_find_targets(curproxy);
6150
Willy Tarreau2738a142006-07-08 17:28:09 +02006151 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006152 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006153 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006154 (!curproxy->timeout.connect ||
6155 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006156 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006157 " | While not properly invalid, you will certainly encounter various problems\n"
6158 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006159 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006160 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006161 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006162 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006163
Willy Tarreau1fa31262007-12-03 00:36:16 +01006164 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6165 * We must still support older configurations, so let's find out whether those
6166 * parameters have been set or must be copied from contimeouts.
6167 */
6168 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006169 if (!curproxy->timeout.tarpit ||
6170 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006171 /* tarpit timeout not set. We search in the following order:
6172 * default.tarpit, curr.connect, default.connect.
6173 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006174 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006175 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006176 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006177 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006178 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006179 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006180 }
6181 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006182 (!curproxy->timeout.queue ||
6183 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006184 /* queue timeout not set. We search in the following order:
6185 * default.queue, curr.connect, default.connect.
6186 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006187 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006188 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006189 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006190 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006191 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006192 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006193 }
6194 }
6195
Willy Tarreau1620ec32011-08-06 17:05:02 +02006196 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006197 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6198 curproxy->check_req = (char *)malloc(curproxy->check_len);
6199 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006200 }
6201
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006202 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006203 if (curproxy->nb_req_cap) {
6204 if (curproxy->mode == PR_MODE_HTTP) {
6205 curproxy->req_cap_pool = create_pool("ptrcap",
6206 curproxy->nb_req_cap * sizeof(char *),
6207 MEM_F_SHARED);
6208 } else {
6209 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6210 proxy_type_str(curproxy), curproxy->id);
6211 err_code |= ERR_WARN;
6212 curproxy->to_log &= ~LW_REQHDR;
6213 curproxy->nb_req_cap = 0;
6214 }
6215 }
6216
6217 if (curproxy->nb_rsp_cap) {
6218 if (curproxy->mode == PR_MODE_HTTP) {
6219 curproxy->rsp_cap_pool = create_pool("ptrcap",
6220 curproxy->nb_rsp_cap * sizeof(char *),
6221 MEM_F_SHARED);
6222 } else {
6223 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6224 proxy_type_str(curproxy), curproxy->id);
6225 err_code |= ERR_WARN;
6226 curproxy->to_log &= ~LW_REQHDR;
6227 curproxy->nb_rsp_cap = 0;
6228 }
6229 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006230
Willy Tarreau196729e2012-05-31 19:30:26 +02006231 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006232 if (!(curproxy->cap & PR_CAP_FE)) {
6233 if (curproxy->logformat_string != default_http_log_format &&
6234 curproxy->logformat_string != default_tcp_log_format &&
6235 curproxy->logformat_string != clf_http_log_format)
6236 free(curproxy->logformat_string);
6237 curproxy->logformat_string = NULL;
6238 }
6239
Willy Tarreau196729e2012-05-31 19:30:26 +02006240 if (curproxy->logformat_string)
6241 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6242
6243 if (curproxy->uniqueid_format_string)
6244 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6245
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 /* first, we will invert the servers list order */
6247 newsrv = NULL;
6248 while (curproxy->srv) {
6249 struct server *next;
6250
6251 next = curproxy->srv->next;
6252 curproxy->srv->next = newsrv;
6253 newsrv = curproxy->srv;
6254 if (!next)
6255 break;
6256 curproxy->srv = next;
6257 }
6258
Willy Tarreaudd701652010-05-25 23:03:02 +02006259 /* assign automatic UIDs to servers which don't have one yet */
6260 next_id = 1;
6261 newsrv = curproxy->srv;
6262 while (newsrv != NULL) {
6263 if (!newsrv->puid) {
6264 /* server ID not set, use automatic numbering with first
6265 * spare entry starting with next_svid.
6266 */
6267 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6268 newsrv->conf.id.key = newsrv->puid = next_id;
6269 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6270 }
6271 next_id++;
6272 newsrv = newsrv->next;
6273 }
6274
Willy Tarreau20697042007-11-15 23:26:18 +01006275 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006276 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277
Willy Tarreau62c3be22012-01-20 13:12:32 +01006278 /*
6279 * If this server supports a maxconn parameter, it needs a dedicated
6280 * tasks to fill the emptied slots when a connection leaves.
6281 * Also, resolve deferred tracking dependency if needed.
6282 */
6283 newsrv = curproxy->srv;
6284 while (newsrv != NULL) {
6285 if (newsrv->minconn > newsrv->maxconn) {
6286 /* Only 'minconn' was specified, or it was higher than or equal
6287 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6288 * this will avoid further useless expensive computations.
6289 */
6290 newsrv->maxconn = newsrv->minconn;
6291 } else if (newsrv->maxconn && !newsrv->minconn) {
6292 /* minconn was not specified, so we set it to maxconn */
6293 newsrv->minconn = newsrv->maxconn;
6294 }
6295
6296 if (newsrv->trackit) {
6297 struct proxy *px;
6298 struct server *srv;
6299 char *pname, *sname;
6300
6301 pname = newsrv->trackit;
6302 sname = strrchr(pname, '/');
6303
6304 if (sname)
6305 *sname++ = '\0';
6306 else {
6307 sname = pname;
6308 pname = NULL;
6309 }
6310
6311 if (pname) {
6312 px = findproxy(pname, PR_CAP_BE);
6313 if (!px) {
6314 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6315 proxy_type_str(curproxy), curproxy->id,
6316 newsrv->id, pname);
6317 cfgerr++;
6318 goto next_srv;
6319 }
6320 } else
6321 px = curproxy;
6322
6323 srv = findserver(px, sname);
6324 if (!srv) {
6325 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6326 proxy_type_str(curproxy), curproxy->id,
6327 newsrv->id, sname);
6328 cfgerr++;
6329 goto next_srv;
6330 }
6331
6332 if (!(srv->state & SRV_CHECKED)) {
6333 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6334 "tracking as it does not have checks enabled.\n",
6335 proxy_type_str(curproxy), curproxy->id,
6336 newsrv->id, px->id, srv->id);
6337 cfgerr++;
6338 goto next_srv;
6339 }
6340
6341 if (curproxy != px &&
6342 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6343 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6344 "tracking: disable-on-404 option inconsistency.\n",
6345 proxy_type_str(curproxy), curproxy->id,
6346 newsrv->id, px->id, srv->id);
6347 cfgerr++;
6348 goto next_srv;
6349 }
6350
6351 /* if the other server is forced disabled, we have to do the same here */
6352 if (srv->state & SRV_MAINTAIN) {
6353 newsrv->state |= SRV_MAINTAIN;
6354 newsrv->state &= ~SRV_RUNNING;
6355 newsrv->health = 0;
6356 }
6357
6358 newsrv->track = srv;
6359 newsrv->tracknext = srv->tracknext;
6360 srv->tracknext = newsrv;
6361
6362 free(newsrv->trackit);
6363 newsrv->trackit = NULL;
6364 }
6365 next_srv:
6366 newsrv = newsrv->next;
6367 }
6368
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006369 /* We have to initialize the server lookup mechanism depending
6370 * on what LB algorithm was choosen.
6371 */
6372
6373 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6374 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6375 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006376 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6377 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6378 init_server_map(curproxy);
6379 } else {
6380 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6381 fwrr_init_server_groups(curproxy);
6382 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006383 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006384
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006385 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006386 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6387 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6388 fwlc_init_server_tree(curproxy);
6389 } else {
6390 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6391 fas_init_server_tree(curproxy);
6392 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006393 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006394
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006395 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006396 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6397 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6398 chash_init_server_tree(curproxy);
6399 } else {
6400 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6401 init_server_map(curproxy);
6402 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006403 break;
6404 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405
6406 if (curproxy->options & PR_O_LOGASAP)
6407 curproxy->to_log &= ~LW_BYTES;
6408
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006409 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006410 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006411 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6412 proxy_type_str(curproxy), curproxy->id);
6413 err_code |= ERR_WARN;
6414 }
6415
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006416 if (curproxy->mode != PR_MODE_HTTP) {
6417 int optnum;
6418
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006419 if (curproxy->uri_auth) {
6420 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6421 proxy_type_str(curproxy), curproxy->id);
6422 err_code |= ERR_WARN;
6423 curproxy->uri_auth = NULL;
6424 }
6425
Willy Tarreau87cf5142011-08-19 22:57:24 +02006426 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006427 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6428 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6429 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006430 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006431 }
6432
6433 if (curproxy->options & PR_O_ORGTO) {
6434 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6435 "originalto", proxy_type_str(curproxy), curproxy->id);
6436 err_code |= ERR_WARN;
6437 curproxy->options &= ~PR_O_ORGTO;
6438 }
6439
6440 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6441 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6442 (curproxy->cap & cfg_opts[optnum].cap) &&
6443 (curproxy->options & cfg_opts[optnum].val)) {
6444 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6445 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6446 err_code |= ERR_WARN;
6447 curproxy->options &= ~cfg_opts[optnum].val;
6448 }
6449 }
6450
6451 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6452 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6453 (curproxy->cap & cfg_opts2[optnum].cap) &&
6454 (curproxy->options2 & cfg_opts2[optnum].val)) {
6455 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6456 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6457 err_code |= ERR_WARN;
6458 curproxy->options2 &= ~cfg_opts2[optnum].val;
6459 }
6460 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006461
Willy Tarreauefa5f512010-03-30 20:13:29 +02006462#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006463 if (curproxy->bind_hdr_occ) {
6464 curproxy->bind_hdr_occ = 0;
6465 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6466 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6467 err_code |= ERR_WARN;
6468 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006469#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006470 }
6471
Willy Tarreaubaaee002006-06-26 02:48:02 +02006472 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006473 * ensure that we're not cross-dressing a TCP server into HTTP.
6474 */
6475 newsrv = curproxy->srv;
6476 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006477 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006478 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6479 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006480 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006481 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006482
Willy Tarreau0cec3312011-10-31 13:49:26 +01006483 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6484 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6485 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6486 err_code |= ERR_WARN;
6487 }
6488
Willy Tarreauefa5f512010-03-30 20:13:29 +02006489#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006490 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6491 newsrv->bind_hdr_occ = 0;
6492 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6493 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6494 err_code |= ERR_WARN;
6495 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006496#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006497 newsrv = newsrv->next;
6498 }
6499
Willy Tarreauc1a21672009-08-16 22:37:44 +02006500 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006501 curproxy->accept = frontend_accept;
6502
Willy Tarreauc1a21672009-08-16 22:37:44 +02006503 if (curproxy->tcp_req.inspect_delay ||
6504 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006505 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006506
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006507 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006508 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006509 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006510 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006511
6512 /* both TCP and HTTP must check switching rules */
6513 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6514 }
6515
6516 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006517 if (curproxy->tcp_req.inspect_delay ||
6518 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6519 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6520
Emeric Brun97679e72010-09-23 17:56:44 +02006521 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6522 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6523
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006524 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006525 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006526 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006527 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006528
6529 /* If the backend does requires RDP cookie persistence, we have to
6530 * enable the corresponding analyser.
6531 */
6532 if (curproxy->options2 & PR_O2_RDPC_PRST)
6533 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6534 }
6535
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006536 listener = NULL;
6537 while (curproxy->listen) {
6538 struct listener *next;
6539
6540 next = curproxy->listen->next;
6541 curproxy->listen->next = listener;
6542 listener = curproxy->listen;
6543
6544 if (!next)
6545 break;
6546
6547 curproxy->listen = next;
6548 }
6549
Willy Tarreaue6b98942007-10-29 01:09:36 +01006550 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006551 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006552 listener = curproxy->listen;
6553 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006554 if (!listener->luid) {
6555 /* listener ID not set, use automatic numbering with first
6556 * spare entry starting with next_luid.
6557 */
6558 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6559 listener->conf.id.key = listener->luid = next_id;
6560 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006561 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006562 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006563
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006564 /* enable separate counters */
6565 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6566 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6567 if (!listener->name) {
6568 sprintf(trash, "sock-%d", listener->luid);
6569 listener->name = strdup(trash);
6570 }
6571 }
6572
Willy Tarreaue6b98942007-10-29 01:09:36 +01006573 if (curproxy->options & PR_O_TCP_NOLING)
6574 listener->options |= LI_O_NOLINGER;
6575 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006576 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006577 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006578 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006579 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006580 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006581 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006582
Willy Tarreau8a956912010-10-15 14:27:08 +02006583 if (listener->options & LI_O_ACC_PROXY)
6584 listener->analysers |= AN_REQ_DECODE_PROXY;
6585
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006586 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6587 listener->options |= LI_O_TCP_RULES;
6588
Willy Tarreaude3041d2010-05-31 10:56:17 +02006589 if (curproxy->mon_mask.s_addr)
6590 listener->options |= LI_O_CHK_MONNET;
6591
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006592 /* smart accept mode is automatic in HTTP mode */
6593 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6594 (curproxy->mode == PR_MODE_HTTP &&
6595 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6596 listener->options |= LI_O_NOQUICKACK;
6597
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006598 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006599 listener = listener->next;
6600 }
6601
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006602 /* Check multi-process mode compatibility for the current proxy */
6603 if (global.nbproc > 1) {
6604 int nbproc = 0;
6605 if (curproxy->bind_proc) {
6606 int proc;
6607 for (proc = 0; proc < global.nbproc; proc++) {
6608 if (curproxy->bind_proc & (1 << proc)) {
6609 nbproc++;
6610 }
6611 }
6612 } else {
6613 nbproc = global.nbproc;
6614 }
6615 if (curproxy->table.peers.name) {
6616 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6617 curproxy->id);
6618 cfgerr++;
6619 }
6620 if (nbproc > 1) {
6621 if (curproxy->uri_auth) {
6622 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6623 curproxy->id);
6624 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6625 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6626 curproxy->id);
6627 }
6628 }
6629 if (curproxy->appsession_name) {
6630 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6631 curproxy->id);
6632 }
6633 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6634 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6635 curproxy->id);
6636 }
6637 }
6638 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006639
6640 /* create the task associated with the proxy */
6641 curproxy->task = task_new();
6642 if (curproxy->task) {
6643 curproxy->task->context = curproxy;
6644 curproxy->task->process = manage_proxy;
6645 /* no need to queue, it will be done automatically if some
6646 * listener gets limited.
6647 */
6648 curproxy->task->expire = TICK_ETERNITY;
6649 } else {
6650 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6651 curproxy->id);
6652 cfgerr++;
6653 }
6654
Willy Tarreaubaaee002006-06-26 02:48:02 +02006655 curproxy = curproxy->next;
6656 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006657
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006658 /* Check multi-process mode compatibility */
6659 if (global.nbproc > 1) {
6660 if (global.stats_fe) {
6661 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6662 }
6663 }
6664
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006665 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6666 struct auth_users *curuser;
6667 int g;
6668
6669 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6670 unsigned int group_mask = 0;
6671 char *group = NULL;
6672
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006673 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006674 continue;
6675
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006676 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006677
6678 for (g = 0; g < curuserlist->grpcnt; g++)
6679 if (!strcmp(curuserlist->groups[g], group))
6680 break;
6681
6682 if (g == curuserlist->grpcnt) {
6683 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6684 curuserlist->name, group, curuser->user);
6685 err_code |= ERR_ALERT | ERR_FATAL;
6686 goto out;
6687 }
6688
6689 group_mask |= (1 << g);
6690 }
6691
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006692 free(curuser->u.groups);
6693 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006694 }
6695
6696 for (g = 0; g < curuserlist->grpcnt; g++) {
6697 char *user = NULL;
6698
6699 if (!curuserlist->groupusers[g])
6700 continue;
6701
6702 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6703 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6704 if (!strcmp(curuser->user, user))
6705 break;
6706
6707 if (!curuser) {
6708 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6709 curuserlist->name, user, curuserlist->groups[g]);
6710 err_code |= ERR_ALERT | ERR_FATAL;
6711 goto out;
6712 }
6713
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006714 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006715 }
6716
6717 free(curuserlist->groupusers[g]);
6718 }
6719
6720 free(curuserlist->groupusers);
6721
6722#ifdef DEBUG_AUTH
6723 for (g = 0; g < curuserlist->grpcnt; g++) {
6724 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6725
6726 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006727 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006728 fprintf(stderr, " %s", curuser->user);
6729 }
6730
6731 fprintf(stderr, "\n");
6732 }
6733#endif
6734
Willy Tarreaufbb78422011-06-05 15:38:35 +02006735 }
6736
6737 /* automatically compute fullconn if not set. We must not do it in the
6738 * loop above because cross-references are not yet fully resolved.
6739 */
6740 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6741 /* If <fullconn> is not set, let's set it to 10% of the sum of
6742 * the possible incoming frontend's maxconns.
6743 */
6744 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6745 struct proxy *fe;
6746 int total = 0;
6747
6748 /* sum up the number of maxconns of frontends which
6749 * reference this backend at least once or which are
6750 * the same one ('listen').
6751 */
6752 for (fe = proxy; fe; fe = fe->next) {
6753 struct switching_rule *rule;
6754 struct hdr_exp *exp;
6755 int found = 0;
6756
6757 if (!(fe->cap & PR_CAP_FE))
6758 continue;
6759
6760 if (fe == curproxy) /* we're on a "listen" instance */
6761 found = 1;
6762
6763 if (fe->defbe.be == curproxy) /* "default_backend" */
6764 found = 1;
6765
6766 /* check if a "use_backend" rule matches */
6767 if (!found) {
6768 list_for_each_entry(rule, &fe->switching_rules, list) {
6769 if (rule->be.backend == curproxy) {
6770 found = 1;
6771 break;
6772 }
6773 }
6774 }
6775
6776 /* check if a "reqsetbe" rule matches */
6777 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6778 if (exp->action == ACT_SETBE &&
6779 (struct proxy *)exp->replace == curproxy) {
6780 found = 1;
6781 break;
6782 }
6783 }
6784
6785 /* now we've checked all possible ways to reference a backend
6786 * from a frontend.
6787 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006788 if (!found)
6789 continue;
6790 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006791 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006792 /* we have the sum of the maxconns in <total>. We only
6793 * keep 10% of that sum to set the default fullconn, with
6794 * a hard minimum of 1 (to avoid a divide by zero).
6795 */
6796 curproxy->fullconn = (total + 9) / 10;
6797 if (!curproxy->fullconn)
6798 curproxy->fullconn = 1;
6799 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 }
6801
Willy Tarreau056f5682010-06-06 15:51:11 +02006802 /* initialize stick-tables on backend capable proxies. This must not
6803 * be done earlier because the data size may be discovered while parsing
6804 * other proxies.
6805 */
6806 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006807 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006808
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006809 /*
6810 * Recount currently required checks.
6811 */
6812
6813 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6814 int optnum;
6815
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006816 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6817 if (curproxy->options & cfg_opts[optnum].val)
6818 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006819
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006820 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6821 if (curproxy->options2 & cfg_opts2[optnum].val)
6822 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006823 }
6824
Willy Tarreau122541c2011-09-07 21:24:49 +02006825 if (peers) {
6826 struct peers *curpeers = peers, **last;
6827 struct peer *p, *pb;
6828
6829 /* Remove all peers sections which don't have a valid listener.
6830 * This can happen when a peers section is never referenced and
6831 * does not contain a local peer.
6832 */
6833 last = &peers;
6834 while (*last) {
6835 curpeers = *last;
6836 if (curpeers->peers_fe) {
6837 last = &curpeers->next;
6838 continue;
6839 }
6840
6841 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6842 curpeers->id, localpeer);
6843
6844 p = curpeers->remote;
6845 while (p) {
6846 pb = p->next;
6847 free(p->id);
6848 free(p);
6849 p = pb;
6850 }
6851
6852 /* Destroy and unlink this curpeers section.
6853 * Note: curpeers is backed up into *last.
6854 */
6855 free(curpeers->id);
6856 curpeers = curpeers->next;
6857 free(*last);
6858 *last = curpeers;
6859 }
6860 }
6861
Willy Tarreauac1932d2011-10-24 19:14:41 +02006862 if (!global.tune.max_http_hdr)
6863 global.tune.max_http_hdr = MAX_HTTP_HDR;
6864
Willy Tarreau34eb6712011-10-24 18:15:04 +02006865 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006866 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006867 MEM_F_SHARED);
6868
Willy Tarreaubb925012009-07-23 13:36:36 +02006869 if (cfgerr > 0)
6870 err_code |= ERR_ALERT | ERR_FATAL;
6871 out:
6872 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006873}
6874
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006875/*
6876 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6877 * parsing sessions.
6878 */
6879void cfg_register_keywords(struct cfg_kw_list *kwl)
6880{
6881 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6882}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006883
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006884/*
6885 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6886 */
6887void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6888{
6889 LIST_DEL(&kwl->list);
6890 LIST_INIT(&kwl->list);
6891}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006892
6893/*
6894 * Local variables:
6895 * c-indent-level: 8
6896 * c-basic-offset: 8
6897 * End:
6898 */