blob: 7a0e9783b8d6ae505efbcb96022a70524d2652c1 [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 Tarreau39b06652012-06-01 10:58:06 +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)
Willy Tarreau196729e2012-05-31 19:30:26 +02001616 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 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004409 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4410 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4411 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4412 else {
4413 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4414 file, linenum, args[cur_arg], args[cur_arg + 1]);
4415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418
4419 cur_arg += 2;
4420 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004421 else if (!strcmp(args[cur_arg], "error-limit")) {
4422 if (!*args[cur_arg + 1]) {
4423 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4424 file, linenum, args[cur_arg]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 }
4428
4429 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4430
4431 if (newsrv->consecutive_errors_limit <= 0) {
4432 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4433 file, linenum, args[cur_arg]);
4434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
4436 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004437 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004438 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004439 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004440 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004441 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004442
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004444#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004445 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004446 file, linenum, "source", "usesrc");
4447#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004448 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004450#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 }
4454 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004455 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4456 if (!sk) {
4457 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
4460 }
4461 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004462
4463 if (port_low != port_high) {
4464 int i;
4465 if (port_low <= 0 || port_low > 65535 ||
4466 port_high <= 0 || port_high > 65535 ||
4467 port_low > port_high) {
4468 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4469 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004472 }
4473 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4474 for (i = 0; i < newsrv->sport_range->size; i++)
4475 newsrv->sport_range->ports[i] = port_low + i;
4476 }
4477
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004479 while (*(args[cur_arg])) {
4480 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004481#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4482#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004483 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4484 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4485 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004488 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004489#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004490 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004491 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004492 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004495 }
4496 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004497 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004498 newsrv->state |= SRV_TPROXY_CLI;
4499 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004500 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004501 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004502 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4503 char *name, *end;
4504
4505 name = args[cur_arg+1] + 7;
4506 while (isspace(*name))
4507 name++;
4508
4509 end = name;
4510 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4511 end++;
4512
4513 newsrv->state &= ~SRV_TPROXY_MASK;
4514 newsrv->state |= SRV_TPROXY_DYN;
4515 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4516 newsrv->bind_hdr_len = end - name;
4517 memcpy(newsrv->bind_hdr_name, name, end - name);
4518 newsrv->bind_hdr_name[end-name] = '\0';
4519 newsrv->bind_hdr_occ = -1;
4520
4521 /* now look for an occurrence number */
4522 while (isspace(*end))
4523 end++;
4524 if (*end == ',') {
4525 end++;
4526 name = end;
4527 if (*end == '-')
4528 end++;
4529 while (isdigit(*end))
4530 end++;
4531 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4532 }
4533
4534 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4535 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4536 " occurrences values smaller than %d.\n",
4537 file, linenum, MAX_HDR_HISTORY);
4538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
4540 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004541 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004542 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004543 if (!sk) {
4544 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
4547 }
4548 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004549 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004550 }
4551 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004552#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004553 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004554#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004555 cur_arg += 2;
4556 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004557#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004558 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004559 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004562#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4563 } /* "usesrc" */
4564
4565 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4566#ifdef SO_BINDTODEVICE
4567 if (!*args[cur_arg + 1]) {
4568 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4569 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004572 }
4573 if (newsrv->iface_name)
4574 free(newsrv->iface_name);
4575
4576 newsrv->iface_name = strdup(args[cur_arg + 1]);
4577 newsrv->iface_len = strlen(newsrv->iface_name);
4578 global.last_checks |= LSTCHK_NETADM;
4579#else
4580 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4581 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004584#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004585 cur_arg += 2;
4586 continue;
4587 }
4588 /* this keyword in not an option of "source" */
4589 break;
4590 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004592 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004593 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4594 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004599 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004600 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 +01004601 file, linenum, newsrv->id);
4602 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004603 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 +01004604 file, linenum);
4605
Willy Tarreau93893792009-07-23 13:19:11 +02004606 err_code |= ERR_ALERT | ERR_FATAL;
4607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 }
4609 }
4610
4611 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004612 if (newsrv->trackit) {
4613 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4614 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004617 }
4618
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004619 /* try to get the port from check_addr if check_port not set */
4620 if (!newsrv->check_port)
4621 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004622
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4624 newsrv->check_port = realport; /* by default */
4625 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004626 /* not yet valid, because no port was set on
4627 * the server either. We'll check if we have
4628 * a known port on the first listener.
4629 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004630 struct listener *l = curproxy->listen;
4631 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4632 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004633 }
4634 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4636 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004640
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004641 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004642 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004643 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4644 err_code |= ERR_ALERT | ERR_ABORT;
4645 goto out;
4646 }
4647
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004648 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 newsrv->state |= SRV_CHECKED;
4650 }
4651
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004652 if (!defsrv) {
4653 if (newsrv->state & SRV_BACKUP)
4654 curproxy->srv_bck++;
4655 else
4656 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004657
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004658 newsrv->prev_state = newsrv->state;
4659 }
William Lallemanda73203e2012-03-12 12:48:57 +01004660 }
4661
4662 else if (strcmp(args[0], "unique-id-format") == 0) {
4663 if (!*(args[1])) {
4664 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4665 err_code |= ERR_ALERT | ERR_FATAL;
4666 goto out;
4667 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004668 free(curproxy->uniqueid_format_string);
4669 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004670 }
William Lallemanda73203e2012-03-12 12:48:57 +01004671
4672 else if (strcmp(args[0], "unique-id-header") == 0) {
4673 if (!*(args[1])) {
4674 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
4677 }
4678 free(curproxy->header_unique_id);
4679 curproxy->header_unique_id = strdup(args[1]);
4680 }
4681
William Lallemand723b73a2012-02-08 16:37:49 +01004682 else if (strcmp(args[0], "log-format") == 0) {
4683 if (!*(args[1])) {
4684 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004688
4689 if (curproxy->logformat_string != default_http_log_format &&
4690 curproxy->logformat_string != default_tcp_log_format &&
4691 curproxy->logformat_string != clf_http_log_format)
4692 free(curproxy->logformat_string);
4693 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 }
William Lallemand723b73a2012-02-08 16:37:49 +01004695
William Lallemand0f99e342011-10-12 17:50:54 +02004696 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4697 /* delete previous herited or defined syslog servers */
4698 struct logsrv *back;
4699
4700 if (*(args[1]) != 0) {
4701 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4702 err_code |= ERR_ALERT | ERR_FATAL;
4703 goto out;
4704 }
4705
William Lallemand723b73a2012-02-08 16:37:49 +01004706 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4707 LIST_DEL(&tmplogsrv->list);
4708 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004709 }
4710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004712 struct logsrv *logsrv;
4713
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004715 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004716 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004717 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004718 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004719 LIST_INIT(&node->list);
4720 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 }
4723 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004724
4725 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004726
William Lallemand0f99e342011-10-12 17:50:54 +02004727 logsrv->facility = get_log_facility(args[2]);
4728 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
4732
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
4734
William Lallemand0f99e342011-10-12 17:50:54 +02004735 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004737 logsrv->level = get_log_level(args[3]);
4738 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 }
4745
William Lallemand0f99e342011-10-12 17:50:54 +02004746 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004747 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004748 logsrv->minlvl = get_log_level(args[4]);
4749 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004750 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004751 err_code |= ERR_ALERT | ERR_FATAL;
4752 goto out;
4753
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004754 }
4755 }
4756
Robert Tsai81ae1952007-12-05 10:47:29 +01004757 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004758 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004759 if (!sk) {
4760 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004761 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
4764 }
William Lallemand0f99e342011-10-12 17:50:54 +02004765 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004766 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004767 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004768 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004769 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
William Lallemand0f99e342011-10-12 17:50:54 +02004773 logsrv->addr = *sk;
4774 if (!get_host_port(&logsrv->addr))
4775 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 }
William Lallemand0f99e342011-10-12 17:50:54 +02004777
4778 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 }
4780 else {
4781 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4782 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004785 }
4786 }
4787 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004788 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004789 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004790
Willy Tarreau977b8e42006-12-29 14:19:17 +01004791 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004792 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004793
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004795 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4796 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004800
4801 /* we must first clear any optional default setting */
4802 curproxy->options &= ~PR_O_TPXY_MASK;
4803 free(curproxy->iface_name);
4804 curproxy->iface_name = NULL;
4805 curproxy->iface_len = 0;
4806
Willy Tarreaud5191e72010-02-09 20:50:45 +01004807 sk = str2sa(args[1]);
4808 if (!sk) {
4809 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
4812 }
4813 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004815
4816 cur_arg = 2;
4817 while (*(args[cur_arg])) {
4818 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004819#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4820#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004821 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4822 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4823 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004826 }
4827#endif
4828 if (!*args[cur_arg + 1]) {
4829 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4830 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004833 }
4834
4835 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004836 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004837 curproxy->options |= PR_O_TPXY_CLI;
4838 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004839 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004840 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004841 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4842 char *name, *end;
4843
4844 name = args[cur_arg+1] + 7;
4845 while (isspace(*name))
4846 name++;
4847
4848 end = name;
4849 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4850 end++;
4851
4852 curproxy->options &= ~PR_O_TPXY_MASK;
4853 curproxy->options |= PR_O_TPXY_DYN;
4854 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4855 curproxy->bind_hdr_len = end - name;
4856 memcpy(curproxy->bind_hdr_name, name, end - name);
4857 curproxy->bind_hdr_name[end-name] = '\0';
4858 curproxy->bind_hdr_occ = -1;
4859
4860 /* now look for an occurrence number */
4861 while (isspace(*end))
4862 end++;
4863 if (*end == ',') {
4864 end++;
4865 name = end;
4866 if (*end == '-')
4867 end++;
4868 while (isdigit(*end))
4869 end++;
4870 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4871 }
4872
4873 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4874 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4875 " occurrences values smaller than %d.\n",
4876 file, linenum, MAX_HDR_HISTORY);
4877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004880 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004881 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004882 if (!sk) {
4883 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004888 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004889 }
4890 global.last_checks |= LSTCHK_NETADM;
4891#if !defined(CONFIG_HAP_LINUX_TPROXY)
4892 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004893#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004894#else /* no TPROXY support */
4895 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004896 file, linenum, "usesrc");
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#endif
4900 cur_arg += 2;
4901 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004902 }
4903
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004904 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4905#ifdef SO_BINDTODEVICE
4906 if (!*args[cur_arg + 1]) {
4907 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004911 }
4912 if (curproxy->iface_name)
4913 free(curproxy->iface_name);
4914
4915 curproxy->iface_name = strdup(args[cur_arg + 1]);
4916 curproxy->iface_len = strlen(curproxy->iface_name);
4917 global.last_checks |= LSTCHK_NETADM;
4918#else
4919 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4920 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004923#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004924 cur_arg += 2;
4925 continue;
4926 }
4927 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4928 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004933 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4934 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4935 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004938 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946
4947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004948 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004949 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
4967 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004969 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004970 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
4974 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004976 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004977 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004981 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004983 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004984 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004986 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004987 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004988 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004989 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004990 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004991 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004993 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004994 }
4995 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004997 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004998 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005000 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5005 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009
5010 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005011 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005012 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 }
5016 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005017 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005018 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005019 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 }
5023 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005024 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005025 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005026 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 }
5030 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005031 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005032 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005033 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005034 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 }
5037 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005038 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005039 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005040 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005041 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005043 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005044 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005045 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005046 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005047 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005048 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005049 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005052 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005053
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 if (curproxy == &defproxy) {
5055 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005056 err_code |= ERR_ALERT | ERR_FATAL;
5057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005058 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005059 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 if (*(args[1]) == 0) {
5063 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005067
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005068 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005069 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5070 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5071 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
5074 }
5075 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5076 }
5077 else if (*args[2]) {
5078 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5079 file, linenum, args[0], args[2]);
5080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
5082 }
5083
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005084 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005085 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005086 wl->s = strdup(args[1]);
5087 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005088 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
5090 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005091 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005097
Willy Tarreauade5ec42010-01-28 19:33:49 +01005098 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005099 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005100 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
5104 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005106 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005107 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
5111 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005112 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005113 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005114 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005115 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
5118 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5121 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 }
5125
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005127 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005128 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005129 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 }
5132 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005134 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005135 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005136 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 }
5139 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005141 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005142 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
5146 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005147 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005148
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 if (curproxy == &defproxy) {
5150 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005154 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 if (*(args[1]) == 0) {
5158 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
5162
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005163 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005164 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5165 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5166 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
5169 }
5170 err_code |= warnif_cond_requires_req(cond, file, linenum);
5171 }
5172 else if (*args[2]) {
5173 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5174 file, linenum, args[0], args[2]);
5175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
5177 }
5178
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005179 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005180 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005181 wl->s = strdup(args[1]);
5182 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
5184 else if (!strcmp(args[0], "errorloc") ||
5185 !strcmp(args[0], "errorloc302") ||
5186 !strcmp(args[0], "errorloc303")) { /* error location */
5187 int errnum, errlen;
5188 char *err;
5189
Willy Tarreau977b8e42006-12-29 14:19:17 +01005190 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005192
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005194 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
5198
5199 errnum = atol(args[1]);
5200 if (!strcmp(args[0], "errorloc303")) {
5201 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5202 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5203 } else {
5204 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5205 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5206 }
5207
Willy Tarreau0f772532006-12-23 20:51:41 +01005208 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5209 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005210 chunk_destroy(&curproxy->errmsg[rc]);
5211 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005212 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005215
5216 if (rc >= HTTP_ERR_SIZE) {
5217 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5218 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 free(err);
5220 }
5221 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005222 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5223 int errnum, errlen, fd;
5224 char *err;
5225 struct stat stat;
5226
5227 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005228 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229
5230 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005231 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005234 }
5235
5236 fd = open(args[2], O_RDONLY);
5237 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5238 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5239 file, linenum, args[2], args[1]);
5240 if (fd >= 0)
5241 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005244 }
5245
Willy Tarreau27a674e2009-08-17 07:23:33 +02005246 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005247 errlen = stat.st_size;
5248 } else {
5249 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005250 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005252 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005253 }
5254
5255 err = malloc(errlen); /* malloc() must succeed during parsing */
5256 errnum = read(fd, err, errlen);
5257 if (errnum != errlen) {
5258 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5259 file, linenum, args[2], args[1]);
5260 close(fd);
5261 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005264 }
5265 close(fd);
5266
5267 errnum = atol(args[1]);
5268 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5269 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005270 chunk_destroy(&curproxy->errmsg[rc]);
5271 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005272 break;
5273 }
5274 }
5275
5276 if (rc >= HTTP_ERR_SIZE) {
5277 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5278 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005280 free(err);
5281 }
5282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005284 struct cfg_kw_list *kwl;
5285 int index;
5286
5287 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5288 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5289 if (kwl->kw[index].section != CFG_LISTEN)
5290 continue;
5291 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5292 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005293 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005294 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005295 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005296 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005297 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005300 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005301 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005302 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_WARN;
5304 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005305 }
Willy Tarreau93893792009-07-23 13:19:11 +02005306 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005307 }
5308 }
5309 }
5310
Willy Tarreau6daf3432008-01-22 16:44:08 +01005311 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
Willy Tarreau93893792009-07-23 13:19:11 +02005315 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005316 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005317 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318}
5319
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005320int
5321cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5322{
5323
5324 int err_code = 0;
5325 const char *err;
5326
5327 if (!strcmp(args[0], "userlist")) { /* new userlist */
5328 struct userlist *newul;
5329
5330 if (!*args[1]) {
5331 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5332 file, linenum, args[0]);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336
5337 err = invalid_char(args[1]);
5338 if (err) {
5339 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5340 file, linenum, *err, args[0], args[1]);
5341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
5343 }
5344
5345 for (newul = userlist; newul; newul = newul->next)
5346 if (!strcmp(newul->name, args[1])) {
5347 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5348 file, linenum, args[1]);
5349 err_code |= ERR_WARN;
5350 goto out;
5351 }
5352
5353 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5354 if (!newul) {
5355 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5356 err_code |= ERR_ALERT | ERR_ABORT;
5357 goto out;
5358 }
5359
5360 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5361 newul->name = strdup(args[1]);
5362
5363 if (!newul->groupusers | !newul->name) {
5364 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5365 err_code |= ERR_ALERT | ERR_ABORT;
5366 goto out;
5367 }
5368
5369 newul->next = userlist;
5370 userlist = newul;
5371
5372 } else if (!strcmp(args[0], "group")) { /* new group */
5373 int cur_arg, i;
5374 const char *err;
5375
5376 if (!*args[1]) {
5377 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5378 file, linenum, args[0]);
5379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
5381 }
5382
5383 err = invalid_char(args[1]);
5384 if (err) {
5385 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5386 file, linenum, *err, args[0], args[1]);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 }
5390
5391 for(i = 0; i < userlist->grpcnt; i++)
5392 if (!strcmp(userlist->groups[i], args[1])) {
5393 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5394 file, linenum, args[1], userlist->name);
5395 err_code |= ERR_ALERT;
5396 goto out;
5397 }
5398
5399 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5400 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5401 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
5404 }
5405
5406 cur_arg = 2;
5407
5408 while (*args[cur_arg]) {
5409 if (!strcmp(args[cur_arg], "users")) {
5410 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5411 cur_arg += 2;
5412 continue;
5413 } else {
5414 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5415 file, linenum, args[0]);
5416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
5418 }
5419 }
5420
5421 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5422 } else if (!strcmp(args[0], "user")) { /* new user */
5423 struct auth_users *newuser;
5424 int cur_arg;
5425
5426 if (!*args[1]) {
5427 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5428 file, linenum, args[0]);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432
5433 for (newuser = userlist->users; newuser; newuser = newuser->next)
5434 if (!strcmp(newuser->user, args[1])) {
5435 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5436 file, linenum, args[1], userlist->name);
5437 err_code |= ERR_ALERT;
5438 goto out;
5439 }
5440
5441 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5442 if (!newuser) {
5443 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5444 err_code |= ERR_ALERT | ERR_ABORT;
5445 goto out;
5446 }
5447
5448 newuser->user = strdup(args[1]);
5449
5450 newuser->next = userlist->users;
5451 userlist->users = newuser;
5452
5453 cur_arg = 2;
5454
5455 while (*args[cur_arg]) {
5456 if (!strcmp(args[cur_arg], "password")) {
5457#ifndef CONFIG_HAP_CRYPT
5458 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5459 file, linenum);
5460 err_code |= ERR_ALERT;
5461#endif
5462 newuser->pass = strdup(args[cur_arg + 1]);
5463 cur_arg += 2;
5464 continue;
5465 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5466 newuser->pass = strdup(args[cur_arg + 1]);
5467 newuser->flags |= AU_O_INSECURE;
5468 cur_arg += 2;
5469 continue;
5470 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005471 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005472 cur_arg += 2;
5473 continue;
5474 } else {
5475 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5476 file, linenum, args[0]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480 }
5481 } else {
5482 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 }
5485
5486out:
5487 return err_code;
5488}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489
5490/*
5491 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005492 * Returns the error code, 0 if OK, or any combination of :
5493 * - ERR_ABORT: must abort ASAP
5494 * - ERR_FATAL: we can continue parsing but not start the service
5495 * - ERR_WARN: a warning has been emitted
5496 * - ERR_ALERT: an alert has been emitted
5497 * Only the two first ones can stop processing, the two others are just
5498 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005500int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005502 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 FILE *f;
5504 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005506 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 if ((f=fopen(file,"r")) == NULL)
5509 return -1;
5510
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005511 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005512 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005513 char *end;
5514 char *args[MAX_LINE_ARGS + 1];
5515 char *line = thisline;
5516
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 linenum++;
5518
5519 end = line + strlen(line);
5520
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005521 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5522 /* Check if we reached the limit and the last char is not \n.
5523 * Watch out for the last line without the terminating '\n'!
5524 */
5525 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005526 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005527 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005528 }
5529
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005531 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 line++;
5533
5534 arg = 0;
5535 args[arg] = line;
5536
5537 while (*line && arg < MAX_LINE_ARGS) {
5538 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5539 * C equivalent value. Other combinations left unchanged (eg: \1).
5540 */
5541 if (*line == '\\') {
5542 int skip = 0;
5543 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5544 *line = line[1];
5545 skip = 1;
5546 }
5547 else if (line[1] == 'r') {
5548 *line = '\r';
5549 skip = 1;
5550 }
5551 else if (line[1] == 'n') {
5552 *line = '\n';
5553 skip = 1;
5554 }
5555 else if (line[1] == 't') {
5556 *line = '\t';
5557 skip = 1;
5558 }
5559 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005560 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005561 unsigned char hex1, hex2;
5562 hex1 = toupper(line[2]) - '0';
5563 hex2 = toupper(line[3]) - '0';
5564 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5565 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5566 *line = (hex1<<4) + hex2;
5567 skip = 3;
5568 }
5569 else {
5570 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005571 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 }
5573 }
5574 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005575 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576 end -= skip;
5577 }
5578 line++;
5579 }
5580 else if (*line == '#' || *line == '\n' || *line == '\r') {
5581 /* end of string, end of loop */
5582 *line = 0;
5583 break;
5584 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005585 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005587 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005588 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 line++;
5590 args[++arg] = line;
5591 }
5592 else {
5593 line++;
5594 }
5595 }
5596
5597 /* empty line */
5598 if (!**args)
5599 continue;
5600
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005601 if (*line) {
5602 /* we had to stop due to too many args.
5603 * Let's terminate the string, print the offending part then cut the
5604 * last arg.
5605 */
5606 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5607 line++;
5608 *line = '\0';
5609
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005610 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005611 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005612 err_code |= ERR_ALERT | ERR_FATAL;
5613 args[arg] = line;
5614 }
5615
Willy Tarreau540abe42007-05-02 20:50:16 +02005616 /* zero out remaining args and ensure that at least one entry
5617 * is zeroed out.
5618 */
5619 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 args[arg] = line;
5621 }
5622
Willy Tarreau3842f002009-06-14 11:39:52 +02005623 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005624 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005625 char *tmp;
5626
Willy Tarreau3842f002009-06-14 11:39:52 +02005627 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005628 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005629 for (arg=0; *args[arg+1]; arg++)
5630 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005631 *tmp = '\0'; // fix the next arg to \0
5632 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005633 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005634 else if (!strcmp(args[0], "default")) {
5635 kwm = KWM_DEF;
5636 for (arg=0; *args[arg+1]; arg++)
5637 args[arg] = args[arg+1]; // shift args after inversion
5638 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005639
William Lallemand0f99e342011-10-12 17:50:54 +02005640 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5641 strcmp(args[0], "log") != 0) {
5642 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005643 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005644 }
5645
Willy Tarreau977b8e42006-12-29 14:19:17 +01005646 if (!strcmp(args[0], "listen") ||
5647 !strcmp(args[0], "frontend") ||
5648 !strcmp(args[0], "backend") ||
5649 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005650 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005652 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005653 cursection = strdup(args[0]);
5654 }
5655 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005657 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005658 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005659 }
5660 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005661 confsect = CFG_USERLIST;
5662 free(cursection);
5663 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005664 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005665 else if (!strcmp(args[0], "peers")) {
5666 confsect = CFG_PEERS;
5667 free(cursection);
5668 cursection = strdup(args[0]);
5669 }
5670
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 /* else it's a section keyword */
5672
5673 switch (confsect) {
5674 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005675 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 break;
5677 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005678 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005680 case CFG_USERLIST:
5681 err_code |= cfg_parse_users(file, linenum, args, kwm);
5682 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005683 case CFG_PEERS:
5684 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5685 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005687 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005688 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005690
5691 if (err_code & ERR_ABORT)
5692 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005694 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005695 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005696 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005697 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005698}
5699
Willy Tarreaubb925012009-07-23 13:36:36 +02005700/*
5701 * Returns the error code, 0 if OK, or any combination of :
5702 * - ERR_ABORT: must abort ASAP
5703 * - ERR_FATAL: we can continue parsing but not start the service
5704 * - ERR_WARN: a warning has been emitted
5705 * - ERR_ALERT: an alert has been emitted
5706 * Only the two first ones can stop processing, the two others are just
5707 * indicators.
5708 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005709int check_config_validity()
5710{
5711 int cfgerr = 0;
5712 struct proxy *curproxy = NULL;
5713 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005714 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005715 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005716 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717
5718 /*
5719 * Now, check for the integrity of all that we have collected.
5720 */
5721
5722 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005723 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005725 /* first, we will invert the proxy list order */
5726 curproxy = NULL;
5727 while (proxy) {
5728 struct proxy *next;
5729
5730 next = proxy->next;
5731 proxy->next = curproxy;
5732 curproxy = proxy;
5733 if (!next)
5734 break;
5735 proxy = next;
5736 }
5737
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005739 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005740 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005741 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005742 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005743 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005744 unsigned int next_id;
5745
5746 if (!curproxy->uuid) {
5747 /* proxy ID not set, use automatic numbering with first
5748 * spare entry starting with next_pxid.
5749 */
5750 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5751 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5752 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005753 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005754 next_pxid++;
5755
Willy Tarreau55ea7572007-06-17 19:56:27 +02005756
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005758 /* ensure we don't keep listeners uselessly bound */
5759 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 curproxy = curproxy->next;
5761 continue;
5762 }
5763
Willy Tarreauff01a212009-03-15 13:46:16 +01005764 switch (curproxy->mode) {
5765 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005766 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005767 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005768 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5769 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005770 cfgerr++;
5771 }
5772
5773 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005774 Warning("config : servers will be ignored for %s '%s'.\n",
5775 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005776 break;
5777
5778 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005779 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005780 break;
5781
5782 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005783 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005784 break;
5785 }
5786
5787 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005788 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5789 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 cfgerr++;
5791 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005792
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005793 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005794 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005795 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005796 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5797 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005798 cfgerr++;
5799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005801 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005802 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5803 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005804 cfgerr++;
5805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005807 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005808 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5809 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005810 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005811 }
5812 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005813 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005814 /* If no LB algo is set in a backend, and we're not in
5815 * transparent mode, dispatch mode nor proxy mode, we
5816 * want to use balance roundrobin by default.
5817 */
5818 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5819 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 }
5821 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005822
Willy Tarreau1620ec32011-08-06 17:05:02 +02005823 if (curproxy->options & PR_O_DISPATCH)
5824 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5825 else if (curproxy->options & PR_O_HTTP_PROXY)
5826 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5827 else if (curproxy->options & PR_O_TRANSP)
5828 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005829
Willy Tarreau1620ec32011-08-06 17:05:02 +02005830 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5831 if (curproxy->options & PR_O_DISABLE404) {
5832 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5833 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5834 err_code |= ERR_WARN;
5835 curproxy->options &= ~PR_O_DISABLE404;
5836 }
5837 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5838 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5839 "send-state", proxy_type_str(curproxy), curproxy->id);
5840 err_code |= ERR_WARN;
5841 curproxy->options &= ~PR_O2_CHK_SNDST;
5842 }
Willy Tarreauef781042010-01-27 11:53:01 +01005843 }
5844
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005845 /* if a default backend was specified, let's find it */
5846 if (curproxy->defbe.name) {
5847 struct proxy *target;
5848
Alex Williams96532db2009-11-01 21:27:13 -05005849 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005850 if (!target) {
5851 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5852 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005853 cfgerr++;
5854 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005855 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5856 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005857 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005858 } else {
5859 free(curproxy->defbe.name);
5860 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005861 /* we force the backend to be present on at least all of
5862 * the frontend's processes.
5863 */
5864 target->bind_proc = curproxy->bind_proc ?
5865 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005866
5867 /* Emit a warning if this proxy also has some servers */
5868 if (curproxy->srv) {
5869 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5870 curproxy->id);
5871 err_code |= ERR_WARN;
5872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 }
5874 }
5875
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005876 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005877 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5878 /* map jump target for ACT_SETBE in req_rep chain */
5879 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005880 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005881 struct proxy *target;
5882
Willy Tarreaua496b602006-12-17 23:15:24 +01005883 if (exp->action != ACT_SETBE)
5884 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005885
Alex Williams96532db2009-11-01 21:27:13 -05005886 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005887 if (!target) {
5888 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5889 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005890 cfgerr++;
5891 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005892 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5893 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005894 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005895 } else {
5896 free((void *)exp->replace);
5897 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005898 /* we force the backend to be present on at least all of
5899 * the frontend's processes.
5900 */
5901 target->bind_proc = curproxy->bind_proc ?
5902 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005903 }
5904 }
5905 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005906
5907 /* find the target proxy for 'use_backend' rules */
5908 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005909 struct proxy *target;
5910
Alex Williams96532db2009-11-01 21:27:13 -05005911 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005912
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005913 if (!target) {
5914 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5915 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005916 cfgerr++;
5917 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005918 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5919 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005920 cfgerr++;
5921 } else {
5922 free((void *)rule->be.name);
5923 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005924 /* we force the backend to be present on at least all of
5925 * the frontend's processes.
5926 */
5927 target->bind_proc = curproxy->bind_proc ?
5928 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005929 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005930 }
5931
5932 /* find the target proxy for 'use_backend' rules */
5933 list_for_each_entry(srule, &curproxy->server_rules, list) {
5934 struct server *target = findserver(curproxy, srule->srv.name);
5935
5936 if (!target) {
5937 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5938 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5939 cfgerr++;
5940 continue;
5941 }
5942 free((void *)srule->srv.name);
5943 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005944 }
5945
Emeric Brunb982a3d2010-01-04 15:45:53 +01005946 /* find the target table for 'stick' rules */
5947 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5948 struct proxy *target;
5949
Emeric Brun1d33b292010-01-04 15:47:17 +01005950 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5951 if (mrule->flags & STK_IS_STORE)
5952 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5953
Emeric Brunb982a3d2010-01-04 15:45:53 +01005954 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005955 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005956 else
5957 target = curproxy;
5958
5959 if (!target) {
5960 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5961 curproxy->id, mrule->table.name);
5962 cfgerr++;
5963 }
5964 else if (target->table.size == 0) {
5965 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5966 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5967 cfgerr++;
5968 }
Willy Tarreau12785782012-04-27 21:37:17 +02005969 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5970 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005971 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5972 cfgerr++;
5973 }
5974 else {
5975 free((void *)mrule->table.name);
5976 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005977 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005978 }
5979 }
5980
5981 /* find the target table for 'store response' rules */
5982 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5983 struct proxy *target;
5984
Emeric Brun1d33b292010-01-04 15:47:17 +01005985 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5986
Emeric Brunb982a3d2010-01-04 15:45:53 +01005987 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005988 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005989 else
5990 target = curproxy;
5991
5992 if (!target) {
5993 Alert("Proxy '%s': unable to find store table '%s'.\n",
5994 curproxy->id, mrule->table.name);
5995 cfgerr++;
5996 }
5997 else if (target->table.size == 0) {
5998 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5999 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6000 cfgerr++;
6001 }
Willy Tarreau12785782012-04-27 21:37:17 +02006002 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6003 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006004 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6005 cfgerr++;
6006 }
6007 else {
6008 free((void *)mrule->table.name);
6009 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006010 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006011 }
6012 }
6013
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006014 /* find the target table for 'tcp-request' layer 4 rules */
6015 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6016 struct proxy *target;
6017
Willy Tarreau56123282010-08-06 19:06:56 +02006018 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006019 continue;
6020
6021 if (trule->act_prm.trk_ctr.table.n)
6022 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6023 else
6024 target = curproxy;
6025
6026 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006027 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6028 curproxy->id, trule->act_prm.trk_ctr.table.n,
6029 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006030 cfgerr++;
6031 }
6032 else if (target->table.size == 0) {
6033 Alert("Proxy '%s': table '%s' used but not configured.\n",
6034 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6035 cfgerr++;
6036 }
6037 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006038 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 +02006039 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6040 cfgerr++;
6041 }
6042 else {
6043 free(trule->act_prm.trk_ctr.table.n);
6044 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006045 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006046 * to pass a list of counters to track and allocate them right here using
6047 * stktable_alloc_data_type().
6048 */
6049 }
6050 }
6051
Willy Tarreaud1f96522010-08-03 19:34:32 +02006052 /* find the target table for 'tcp-request' layer 6 rules */
6053 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6054 struct proxy *target;
6055
Willy Tarreau56123282010-08-06 19:06:56 +02006056 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006057 continue;
6058
6059 if (trule->act_prm.trk_ctr.table.n)
6060 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6061 else
6062 target = curproxy;
6063
6064 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006065 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6066 curproxy->id, trule->act_prm.trk_ctr.table.n,
6067 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006068 cfgerr++;
6069 }
6070 else if (target->table.size == 0) {
6071 Alert("Proxy '%s': table '%s' used but not configured.\n",
6072 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6073 cfgerr++;
6074 }
6075 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006076 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 +02006077 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6078 cfgerr++;
6079 }
6080 else {
6081 free(trule->act_prm.trk_ctr.table.n);
6082 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006083 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006084 * to pass a list of counters to track and allocate them right here using
6085 * stktable_alloc_data_type().
6086 */
6087 }
6088 }
6089
Emeric Brun32da3c42010-09-23 18:39:19 +02006090 if (curproxy->table.peers.name) {
6091 struct peers *curpeers = peers;
6092
6093 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6094 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6095 free((void *)curproxy->table.peers.name);
6096 curproxy->table.peers.p = peers;
6097 break;
6098 }
6099 }
6100
6101 if (!curpeers) {
6102 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6103 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006104 free((void *)curproxy->table.peers.name);
6105 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006106 cfgerr++;
6107 }
6108 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006109 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6110 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006111 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006112 cfgerr++;
6113 }
6114 }
6115
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006116 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006117 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006118 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6119 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6120 "proxy", curproxy->id);
6121 cfgerr++;
6122 goto out_uri_auth_compat;
6123 }
6124
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006125 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006126 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006127 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006128 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006129
Willy Tarreau95fa4692010-02-01 13:05:50 +01006130 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6131 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006132
6133 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006134 uri_auth_compat_req[i++] = "realm";
6135 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6136 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006137
Willy Tarreau95fa4692010-02-01 13:05:50 +01006138 uri_auth_compat_req[i++] = "unless";
6139 uri_auth_compat_req[i++] = "{";
6140 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6141 uri_auth_compat_req[i++] = "}";
6142 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006143
Willy Tarreauff011f22011-01-06 17:51:27 +01006144 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6145 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006146 cfgerr++;
6147 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006148 }
6149
Willy Tarreauff011f22011-01-06 17:51:27 +01006150 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006151
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006152 if (curproxy->uri_auth->auth_realm) {
6153 free(curproxy->uri_auth->auth_realm);
6154 curproxy->uri_auth->auth_realm = NULL;
6155 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006156
6157 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006158 }
6159out_uri_auth_compat:
6160
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006161 cfgerr += acl_find_targets(curproxy);
6162
Willy Tarreau2738a142006-07-08 17:28:09 +02006163 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006164 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006165 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006166 (!curproxy->timeout.connect ||
6167 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006168 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006169 " | While not properly invalid, you will certainly encounter various problems\n"
6170 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006171 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006172 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006173 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006174 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006175
Willy Tarreau1fa31262007-12-03 00:36:16 +01006176 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6177 * We must still support older configurations, so let's find out whether those
6178 * parameters have been set or must be copied from contimeouts.
6179 */
6180 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006181 if (!curproxy->timeout.tarpit ||
6182 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006183 /* tarpit timeout not set. We search in the following order:
6184 * default.tarpit, curr.connect, default.connect.
6185 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006186 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006187 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006188 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006189 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006190 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006191 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006192 }
6193 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006194 (!curproxy->timeout.queue ||
6195 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006196 /* queue timeout not set. We search in the following order:
6197 * default.queue, curr.connect, default.connect.
6198 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006199 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006200 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006201 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006202 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006203 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006204 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006205 }
6206 }
6207
Willy Tarreau1620ec32011-08-06 17:05:02 +02006208 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006209 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6210 curproxy->check_req = (char *)malloc(curproxy->check_len);
6211 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006212 }
6213
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006214 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006215 if (curproxy->nb_req_cap) {
6216 if (curproxy->mode == PR_MODE_HTTP) {
6217 curproxy->req_cap_pool = create_pool("ptrcap",
6218 curproxy->nb_req_cap * sizeof(char *),
6219 MEM_F_SHARED);
6220 } else {
6221 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6222 proxy_type_str(curproxy), curproxy->id);
6223 err_code |= ERR_WARN;
6224 curproxy->to_log &= ~LW_REQHDR;
6225 curproxy->nb_req_cap = 0;
6226 }
6227 }
6228
6229 if (curproxy->nb_rsp_cap) {
6230 if (curproxy->mode == PR_MODE_HTTP) {
6231 curproxy->rsp_cap_pool = create_pool("ptrcap",
6232 curproxy->nb_rsp_cap * sizeof(char *),
6233 MEM_F_SHARED);
6234 } else {
6235 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6236 proxy_type_str(curproxy), curproxy->id);
6237 err_code |= ERR_WARN;
6238 curproxy->to_log &= ~LW_REQHDR;
6239 curproxy->nb_rsp_cap = 0;
6240 }
6241 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006242
Willy Tarreau196729e2012-05-31 19:30:26 +02006243 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006244 if (!(curproxy->cap & PR_CAP_FE)) {
6245 if (curproxy->logformat_string != default_http_log_format &&
6246 curproxy->logformat_string != default_tcp_log_format &&
6247 curproxy->logformat_string != clf_http_log_format)
6248 free(curproxy->logformat_string);
6249 curproxy->logformat_string = NULL;
6250 }
6251
Willy Tarreau196729e2012-05-31 19:30:26 +02006252 if (curproxy->logformat_string)
6253 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6254
6255 if (curproxy->uniqueid_format_string)
6256 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6257
Willy Tarreaubaaee002006-06-26 02:48:02 +02006258 /* first, we will invert the servers list order */
6259 newsrv = NULL;
6260 while (curproxy->srv) {
6261 struct server *next;
6262
6263 next = curproxy->srv->next;
6264 curproxy->srv->next = newsrv;
6265 newsrv = curproxy->srv;
6266 if (!next)
6267 break;
6268 curproxy->srv = next;
6269 }
6270
Willy Tarreaudd701652010-05-25 23:03:02 +02006271 /* assign automatic UIDs to servers which don't have one yet */
6272 next_id = 1;
6273 newsrv = curproxy->srv;
6274 while (newsrv != NULL) {
6275 if (!newsrv->puid) {
6276 /* server ID not set, use automatic numbering with first
6277 * spare entry starting with next_svid.
6278 */
6279 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6280 newsrv->conf.id.key = newsrv->puid = next_id;
6281 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6282 }
6283 next_id++;
6284 newsrv = newsrv->next;
6285 }
6286
Willy Tarreau20697042007-11-15 23:26:18 +01006287 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006288 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006289
Willy Tarreau62c3be22012-01-20 13:12:32 +01006290 /*
6291 * If this server supports a maxconn parameter, it needs a dedicated
6292 * tasks to fill the emptied slots when a connection leaves.
6293 * Also, resolve deferred tracking dependency if needed.
6294 */
6295 newsrv = curproxy->srv;
6296 while (newsrv != NULL) {
6297 if (newsrv->minconn > newsrv->maxconn) {
6298 /* Only 'minconn' was specified, or it was higher than or equal
6299 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6300 * this will avoid further useless expensive computations.
6301 */
6302 newsrv->maxconn = newsrv->minconn;
6303 } else if (newsrv->maxconn && !newsrv->minconn) {
6304 /* minconn was not specified, so we set it to maxconn */
6305 newsrv->minconn = newsrv->maxconn;
6306 }
6307
6308 if (newsrv->trackit) {
6309 struct proxy *px;
6310 struct server *srv;
6311 char *pname, *sname;
6312
6313 pname = newsrv->trackit;
6314 sname = strrchr(pname, '/');
6315
6316 if (sname)
6317 *sname++ = '\0';
6318 else {
6319 sname = pname;
6320 pname = NULL;
6321 }
6322
6323 if (pname) {
6324 px = findproxy(pname, PR_CAP_BE);
6325 if (!px) {
6326 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6327 proxy_type_str(curproxy), curproxy->id,
6328 newsrv->id, pname);
6329 cfgerr++;
6330 goto next_srv;
6331 }
6332 } else
6333 px = curproxy;
6334
6335 srv = findserver(px, sname);
6336 if (!srv) {
6337 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6338 proxy_type_str(curproxy), curproxy->id,
6339 newsrv->id, sname);
6340 cfgerr++;
6341 goto next_srv;
6342 }
6343
6344 if (!(srv->state & SRV_CHECKED)) {
6345 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6346 "tracking as it does not have checks enabled.\n",
6347 proxy_type_str(curproxy), curproxy->id,
6348 newsrv->id, px->id, srv->id);
6349 cfgerr++;
6350 goto next_srv;
6351 }
6352
6353 if (curproxy != px &&
6354 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6355 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6356 "tracking: disable-on-404 option inconsistency.\n",
6357 proxy_type_str(curproxy), curproxy->id,
6358 newsrv->id, px->id, srv->id);
6359 cfgerr++;
6360 goto next_srv;
6361 }
6362
6363 /* if the other server is forced disabled, we have to do the same here */
6364 if (srv->state & SRV_MAINTAIN) {
6365 newsrv->state |= SRV_MAINTAIN;
6366 newsrv->state &= ~SRV_RUNNING;
6367 newsrv->health = 0;
6368 }
6369
6370 newsrv->track = srv;
6371 newsrv->tracknext = srv->tracknext;
6372 srv->tracknext = newsrv;
6373
6374 free(newsrv->trackit);
6375 newsrv->trackit = NULL;
6376 }
6377 next_srv:
6378 newsrv = newsrv->next;
6379 }
6380
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006381 /* We have to initialize the server lookup mechanism depending
6382 * on what LB algorithm was choosen.
6383 */
6384
6385 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6386 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6387 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006388 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6389 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6390 init_server_map(curproxy);
6391 } else {
6392 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6393 fwrr_init_server_groups(curproxy);
6394 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006395 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006396
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006397 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006398 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6399 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6400 fwlc_init_server_tree(curproxy);
6401 } else {
6402 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6403 fas_init_server_tree(curproxy);
6404 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006405 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006406
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006407 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006408 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6409 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6410 chash_init_server_tree(curproxy);
6411 } else {
6412 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6413 init_server_map(curproxy);
6414 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006415 break;
6416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417
6418 if (curproxy->options & PR_O_LOGASAP)
6419 curproxy->to_log &= ~LW_BYTES;
6420
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006421 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006422 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006423 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6424 proxy_type_str(curproxy), curproxy->id);
6425 err_code |= ERR_WARN;
6426 }
6427
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006428 if (curproxy->mode != PR_MODE_HTTP) {
6429 int optnum;
6430
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006431 if (curproxy->uri_auth) {
6432 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6433 proxy_type_str(curproxy), curproxy->id);
6434 err_code |= ERR_WARN;
6435 curproxy->uri_auth = NULL;
6436 }
6437
Willy Tarreau87cf5142011-08-19 22:57:24 +02006438 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006439 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6440 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6441 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006442 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006443 }
6444
6445 if (curproxy->options & PR_O_ORGTO) {
6446 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6447 "originalto", proxy_type_str(curproxy), curproxy->id);
6448 err_code |= ERR_WARN;
6449 curproxy->options &= ~PR_O_ORGTO;
6450 }
6451
6452 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6453 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6454 (curproxy->cap & cfg_opts[optnum].cap) &&
6455 (curproxy->options & cfg_opts[optnum].val)) {
6456 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6457 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6458 err_code |= ERR_WARN;
6459 curproxy->options &= ~cfg_opts[optnum].val;
6460 }
6461 }
6462
6463 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6464 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6465 (curproxy->cap & cfg_opts2[optnum].cap) &&
6466 (curproxy->options2 & cfg_opts2[optnum].val)) {
6467 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6468 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6469 err_code |= ERR_WARN;
6470 curproxy->options2 &= ~cfg_opts2[optnum].val;
6471 }
6472 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006473
Willy Tarreauefa5f512010-03-30 20:13:29 +02006474#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006475 if (curproxy->bind_hdr_occ) {
6476 curproxy->bind_hdr_occ = 0;
6477 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6478 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6479 err_code |= ERR_WARN;
6480 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006481#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006482 }
6483
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006485 * ensure that we're not cross-dressing a TCP server into HTTP.
6486 */
6487 newsrv = curproxy->srv;
6488 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006489 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006490 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6491 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006492 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006493 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006494
Willy Tarreau0cec3312011-10-31 13:49:26 +01006495 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6496 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6497 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6498 err_code |= ERR_WARN;
6499 }
6500
Willy Tarreauefa5f512010-03-30 20:13:29 +02006501#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006502 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6503 newsrv->bind_hdr_occ = 0;
6504 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6505 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6506 err_code |= ERR_WARN;
6507 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006508#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006509 newsrv = newsrv->next;
6510 }
6511
Willy Tarreauc1a21672009-08-16 22:37:44 +02006512 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006513 curproxy->accept = frontend_accept;
6514
Willy Tarreauc1a21672009-08-16 22:37:44 +02006515 if (curproxy->tcp_req.inspect_delay ||
6516 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006517 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006518
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006519 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006520 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006521 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006522 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006523
6524 /* both TCP and HTTP must check switching rules */
6525 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6526 }
6527
6528 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006529 if (curproxy->tcp_req.inspect_delay ||
6530 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6531 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6532
Emeric Brun97679e72010-09-23 17:56:44 +02006533 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6534 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6535
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006536 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006537 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006538 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006539 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006540
6541 /* If the backend does requires RDP cookie persistence, we have to
6542 * enable the corresponding analyser.
6543 */
6544 if (curproxy->options2 & PR_O2_RDPC_PRST)
6545 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6546 }
6547
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006548 listener = NULL;
6549 while (curproxy->listen) {
6550 struct listener *next;
6551
6552 next = curproxy->listen->next;
6553 curproxy->listen->next = listener;
6554 listener = curproxy->listen;
6555
6556 if (!next)
6557 break;
6558
6559 curproxy->listen = next;
6560 }
6561
Willy Tarreaue6b98942007-10-29 01:09:36 +01006562 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006563 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006564 listener = curproxy->listen;
6565 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006566 if (!listener->luid) {
6567 /* listener ID not set, use automatic numbering with first
6568 * spare entry starting with next_luid.
6569 */
6570 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6571 listener->conf.id.key = listener->luid = next_id;
6572 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006573 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006574 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006575
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006576 /* enable separate counters */
6577 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6578 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6579 if (!listener->name) {
6580 sprintf(trash, "sock-%d", listener->luid);
6581 listener->name = strdup(trash);
6582 }
6583 }
6584
Willy Tarreaue6b98942007-10-29 01:09:36 +01006585 if (curproxy->options & PR_O_TCP_NOLING)
6586 listener->options |= LI_O_NOLINGER;
6587 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006588 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006589 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006590 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006591 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006592 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006593 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006594
Willy Tarreau8a956912010-10-15 14:27:08 +02006595 if (listener->options & LI_O_ACC_PROXY)
6596 listener->analysers |= AN_REQ_DECODE_PROXY;
6597
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006598 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6599 listener->options |= LI_O_TCP_RULES;
6600
Willy Tarreaude3041d2010-05-31 10:56:17 +02006601 if (curproxy->mon_mask.s_addr)
6602 listener->options |= LI_O_CHK_MONNET;
6603
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006604 /* smart accept mode is automatic in HTTP mode */
6605 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6606 (curproxy->mode == PR_MODE_HTTP &&
6607 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6608 listener->options |= LI_O_NOQUICKACK;
6609
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006610 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006611 listener = listener->next;
6612 }
6613
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006614 /* Check multi-process mode compatibility for the current proxy */
6615 if (global.nbproc > 1) {
6616 int nbproc = 0;
6617 if (curproxy->bind_proc) {
6618 int proc;
6619 for (proc = 0; proc < global.nbproc; proc++) {
6620 if (curproxy->bind_proc & (1 << proc)) {
6621 nbproc++;
6622 }
6623 }
6624 } else {
6625 nbproc = global.nbproc;
6626 }
6627 if (curproxy->table.peers.name) {
6628 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6629 curproxy->id);
6630 cfgerr++;
6631 }
6632 if (nbproc > 1) {
6633 if (curproxy->uri_auth) {
6634 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6635 curproxy->id);
6636 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6637 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6638 curproxy->id);
6639 }
6640 }
6641 if (curproxy->appsession_name) {
6642 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6643 curproxy->id);
6644 }
6645 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6646 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6647 curproxy->id);
6648 }
6649 }
6650 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006651
6652 /* create the task associated with the proxy */
6653 curproxy->task = task_new();
6654 if (curproxy->task) {
6655 curproxy->task->context = curproxy;
6656 curproxy->task->process = manage_proxy;
6657 /* no need to queue, it will be done automatically if some
6658 * listener gets limited.
6659 */
6660 curproxy->task->expire = TICK_ETERNITY;
6661 } else {
6662 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6663 curproxy->id);
6664 cfgerr++;
6665 }
6666
Willy Tarreaubaaee002006-06-26 02:48:02 +02006667 curproxy = curproxy->next;
6668 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006669
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006670 /* Check multi-process mode compatibility */
6671 if (global.nbproc > 1) {
6672 if (global.stats_fe) {
6673 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6674 }
6675 }
6676
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006677 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6678 struct auth_users *curuser;
6679 int g;
6680
6681 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6682 unsigned int group_mask = 0;
6683 char *group = NULL;
6684
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006685 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006686 continue;
6687
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006688 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689
6690 for (g = 0; g < curuserlist->grpcnt; g++)
6691 if (!strcmp(curuserlist->groups[g], group))
6692 break;
6693
6694 if (g == curuserlist->grpcnt) {
6695 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6696 curuserlist->name, group, curuser->user);
6697 err_code |= ERR_ALERT | ERR_FATAL;
6698 goto out;
6699 }
6700
6701 group_mask |= (1 << g);
6702 }
6703
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006704 free(curuser->u.groups);
6705 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006706 }
6707
6708 for (g = 0; g < curuserlist->grpcnt; g++) {
6709 char *user = NULL;
6710
6711 if (!curuserlist->groupusers[g])
6712 continue;
6713
6714 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6715 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6716 if (!strcmp(curuser->user, user))
6717 break;
6718
6719 if (!curuser) {
6720 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6721 curuserlist->name, user, curuserlist->groups[g]);
6722 err_code |= ERR_ALERT | ERR_FATAL;
6723 goto out;
6724 }
6725
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006726 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006727 }
6728
6729 free(curuserlist->groupusers[g]);
6730 }
6731
6732 free(curuserlist->groupusers);
6733
6734#ifdef DEBUG_AUTH
6735 for (g = 0; g < curuserlist->grpcnt; g++) {
6736 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6737
6738 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006739 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006740 fprintf(stderr, " %s", curuser->user);
6741 }
6742
6743 fprintf(stderr, "\n");
6744 }
6745#endif
6746
Willy Tarreaufbb78422011-06-05 15:38:35 +02006747 }
6748
6749 /* automatically compute fullconn if not set. We must not do it in the
6750 * loop above because cross-references are not yet fully resolved.
6751 */
6752 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6753 /* If <fullconn> is not set, let's set it to 10% of the sum of
6754 * the possible incoming frontend's maxconns.
6755 */
6756 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6757 struct proxy *fe;
6758 int total = 0;
6759
6760 /* sum up the number of maxconns of frontends which
6761 * reference this backend at least once or which are
6762 * the same one ('listen').
6763 */
6764 for (fe = proxy; fe; fe = fe->next) {
6765 struct switching_rule *rule;
6766 struct hdr_exp *exp;
6767 int found = 0;
6768
6769 if (!(fe->cap & PR_CAP_FE))
6770 continue;
6771
6772 if (fe == curproxy) /* we're on a "listen" instance */
6773 found = 1;
6774
6775 if (fe->defbe.be == curproxy) /* "default_backend" */
6776 found = 1;
6777
6778 /* check if a "use_backend" rule matches */
6779 if (!found) {
6780 list_for_each_entry(rule, &fe->switching_rules, list) {
6781 if (rule->be.backend == curproxy) {
6782 found = 1;
6783 break;
6784 }
6785 }
6786 }
6787
6788 /* check if a "reqsetbe" rule matches */
6789 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6790 if (exp->action == ACT_SETBE &&
6791 (struct proxy *)exp->replace == curproxy) {
6792 found = 1;
6793 break;
6794 }
6795 }
6796
6797 /* now we've checked all possible ways to reference a backend
6798 * from a frontend.
6799 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006800 if (!found)
6801 continue;
6802 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006803 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006804 /* we have the sum of the maxconns in <total>. We only
6805 * keep 10% of that sum to set the default fullconn, with
6806 * a hard minimum of 1 (to avoid a divide by zero).
6807 */
6808 curproxy->fullconn = (total + 9) / 10;
6809 if (!curproxy->fullconn)
6810 curproxy->fullconn = 1;
6811 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006812 }
6813
Willy Tarreau056f5682010-06-06 15:51:11 +02006814 /* initialize stick-tables on backend capable proxies. This must not
6815 * be done earlier because the data size may be discovered while parsing
6816 * other proxies.
6817 */
6818 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006819 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006820
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006821 /*
6822 * Recount currently required checks.
6823 */
6824
6825 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6826 int optnum;
6827
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006828 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6829 if (curproxy->options & cfg_opts[optnum].val)
6830 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006831
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006832 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6833 if (curproxy->options2 & cfg_opts2[optnum].val)
6834 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006835 }
6836
Willy Tarreau122541c2011-09-07 21:24:49 +02006837 if (peers) {
6838 struct peers *curpeers = peers, **last;
6839 struct peer *p, *pb;
6840
6841 /* Remove all peers sections which don't have a valid listener.
6842 * This can happen when a peers section is never referenced and
6843 * does not contain a local peer.
6844 */
6845 last = &peers;
6846 while (*last) {
6847 curpeers = *last;
6848 if (curpeers->peers_fe) {
6849 last = &curpeers->next;
6850 continue;
6851 }
6852
6853 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6854 curpeers->id, localpeer);
6855
6856 p = curpeers->remote;
6857 while (p) {
6858 pb = p->next;
6859 free(p->id);
6860 free(p);
6861 p = pb;
6862 }
6863
6864 /* Destroy and unlink this curpeers section.
6865 * Note: curpeers is backed up into *last.
6866 */
6867 free(curpeers->id);
6868 curpeers = curpeers->next;
6869 free(*last);
6870 *last = curpeers;
6871 }
6872 }
6873
Willy Tarreauac1932d2011-10-24 19:14:41 +02006874 if (!global.tune.max_http_hdr)
6875 global.tune.max_http_hdr = MAX_HTTP_HDR;
6876
Willy Tarreau34eb6712011-10-24 18:15:04 +02006877 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006878 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006879 MEM_F_SHARED);
6880
Willy Tarreaubb925012009-07-23 13:36:36 +02006881 if (cfgerr > 0)
6882 err_code |= ERR_ALERT | ERR_FATAL;
6883 out:
6884 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006885}
6886
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006887/*
6888 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6889 * parsing sessions.
6890 */
6891void cfg_register_keywords(struct cfg_kw_list *kwl)
6892{
6893 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6894}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006895
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006896/*
6897 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6898 */
6899void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6900{
6901 LIST_DEL(&kwl->list);
6902 LIST_INIT(&kwl->list);
6903}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006904
6905/*
6906 * Local variables:
6907 * c-indent-level: 8
6908 * c-basic-offset: 8
6909 * End:
6910 */