blob: 6a12d4028f856515a6053e17fb13d553f4a7e12b [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 Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
36#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020037#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020042#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020045#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020046#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010048#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020052#include <proto/listener.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 Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#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 Tarreau75bf2c92012-08-20 17:01:35 +020064#include <proto/raw_sock.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
Emeric Brunfc0421f2012-09-07 17:30:07 +020068#ifdef USE_OPENSSL
69#include <types/ssl_sock.h>
70#include <proto/ssl_sock.h>
71#include <proto/shctx.h>
72#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020073
Willy Tarreauf3c69202006-07-09 16:42:34 +020074/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
75 * ssl-hello-chk option to ensure that the remote server speaks SSL.
76 *
77 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
78 */
79const char sslv3_client_hello_pkt[] = {
80 "\x16" /* ContentType : 0x16 = Hanshake */
81 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
82 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
83 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
84 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
85 "\x03\x00" /* Hello Version : 0x0300 = v3 */
86 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
87 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
88 "\x00" /* Session ID length : empty (no session ID) */
89 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
90 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
91 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
92 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
93 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
94 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
95 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
96 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
97 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
98 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
99 "\x00\x38" "\x00\x39" "\x00\x3A"
100 "\x01" /* Compression Length : 0x01 = 1 byte for types */
101 "\x00" /* Compression Type : 0x00 = NULL compression */
102};
103
Willy Tarreau3842f002009-06-14 11:39:52 +0200104/* various keyword modifiers */
105enum kw_mod {
106 KWM_STD = 0, /* normal */
107 KWM_NO, /* "no" prefixed before the keyword */
108 KWM_DEF, /* "default" prefixed before the keyword */
109};
110
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113 const char *name;
114 unsigned int val;
115 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118};
119
120/* proxy->options */
121static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100122{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100123 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
124 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
125 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
127 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
128 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
129 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
133 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100195static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196{
197 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100198 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 int port, end;
200
201 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200202
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 while (next && *next) {
204 struct sockaddr_storage ss;
205
206 str = next;
207 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100208 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 *next++ = 0;
210 }
211
Emeric Bruned760922010-10-22 17:59:25 +0200212 if (*str == '/') {
213 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
214 /* so compute max path */
215 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
216 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 +0200217
Emeric Bruned760922010-10-22 17:59:25 +0200218 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100219 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
220 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200221 goto fail;
222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200225 ss.ss_family = AF_UNIX;
226 if (global.unix_bind.prefix) {
227 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
228 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 }
Emeric Bruned760922010-10-22 17:59:25 +0200230 else {
231 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
232 }
233 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 }
235 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 ss2 = str2sa_range(str, &port, &end);
239 if (!ss2) {
240 Alert("parsing [%s:%d] : invalid listening address: '%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 if (!port) {
246 Alert("parsing [%s:%d] : missing port number: '%s'\n",
247 file, line, str);
248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100251 /* OK the address looks correct */
252 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
Emeric Bruned760922010-10-22 17:59:25 +0200254 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
256 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
262 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 l->next = curproxy->listen;
270 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271
272 l->fd = -1;
273 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200274 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100275 l->state = LI_INIT;
276
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100277 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100279 tcpv4_add_listener(l);
280 }
Emeric Bruned760922010-10-22 17:59:25 +0200281 else if (ss.ss_family == AF_INET6) {
282 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
283 tcpv6_add_listener(l);
284 }
285 else {
286 l->perm.ux.gid = l->perm.ux.uid = -1;
287 l->perm.ux.mode = 0;
288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100417/* Report it if a request ACL condition uses some response-only parameters. It
418 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
419 * Note that <cond> may be NULL and then will be ignored.
420 */
421static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
422{
423 struct acl *acl;
424
425 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
426 return 0;
427
428 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
429 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
430 file, line, acl ? acl->name : "(unknown)");
431 return ERR_WARN;
432}
433
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100434/* Report it if a request ACL condition uses some request-only volatile parameters.
435 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
436 * Note that <cond> may be NULL and then will be ignored.
437 */
438static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
439{
440 struct acl *acl;
441
442 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
443 return 0;
444
445 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
446 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
447 file, line, acl ? acl->name : "(unknown)");
448 return ERR_WARN;
449}
450
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
471 else if (!strcmp(args[0], "daemon")) {
472 global.mode |= MODE_DAEMON;
473 }
474 else if (!strcmp(args[0], "debug")) {
475 global.mode |= MODE_DEBUG;
476 }
477 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200480 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
483 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100487 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100489 else if (!strcmp(args[0], "nosplice")) {
490 global.tune.options &= ~GTUNE_USE_SPLICE;
491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492 else if (!strcmp(args[0], "quiet")) {
493 global.mode |= MODE_QUIET;
494 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 else if (!strcmp(args[0], "tune.maxpollevents")) {
496 if (global.tune.maxpollevents != 0) {
497 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 err_code |= ERR_ALERT;
499 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200500 }
501 if (*(args[1]) == 0) {
502 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 err_code |= ERR_ALERT | ERR_FATAL;
504 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200505 }
506 global.tune.maxpollevents = atol(args[1]);
507 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 else if (!strcmp(args[0], "tune.maxaccept")) {
509 if (global.tune.maxaccept != 0) {
510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200511 err_code |= ERR_ALERT;
512 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100513 }
514 if (*(args[1]) == 0) {
515 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200516 err_code |= ERR_ALERT | ERR_FATAL;
517 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100518 }
519 global.tune.maxaccept = atol(args[1]);
520 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200521 else if (!strcmp(args[0], "tune.chksize")) {
522 if (*(args[1]) == 0) {
523 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
524 err_code |= ERR_ALERT | ERR_FATAL;
525 goto out;
526 }
527 global.tune.chksize = atol(args[1]);
528 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200529#ifdef USE_OPENSSL
530 else if (!strcmp(args[0], "tune.sslcachesize")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.sslcachesize = atol(args[1]);
537 }
538#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 else if (!strcmp(args[0], "tune.bufsize")) {
540 if (*(args[1]) == 0) {
541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT | ERR_FATAL;
543 goto out;
544 }
545 global.tune.bufsize = atol(args[1]);
546 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
547 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200548 trashlen = global.tune.bufsize;
549 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200550 }
551 else if (!strcmp(args[0], "tune.maxrewrite")) {
552 if (*(args[1]) == 0) {
553 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT | ERR_FATAL;
555 goto out;
556 }
557 global.tune.maxrewrite = atol(args[1]);
558 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
559 global.tune.maxrewrite = global.tune.bufsize / 2;
560 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100561 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
562 if (global.tune.client_rcvbuf != 0) {
563 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT;
565 goto out;
566 }
567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.client_rcvbuf = atol(args[1]);
573 }
574 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
575 if (global.tune.server_rcvbuf != 0) {
576 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT;
578 goto out;
579 }
580 if (*(args[1]) == 0) {
581 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584 }
585 global.tune.server_rcvbuf = atol(args[1]);
586 }
587 else if (!strcmp(args[0], "tune.sndbuf.client")) {
588 if (global.tune.client_sndbuf != 0) {
589 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT;
591 goto out;
592 }
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.client_sndbuf = atol(args[1]);
599 }
600 else if (!strcmp(args[0], "tune.sndbuf.server")) {
601 if (global.tune.server_sndbuf != 0) {
602 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT;
604 goto out;
605 }
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.server_sndbuf = atol(args[1]);
612 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200613 else if (!strcmp(args[0], "tune.pipesize")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.pipesize = atol(args[1]);
620 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200621 else if (!strcmp(args[0], "tune.http.maxhdr")) {
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.max_http_hdr = atol(args[1]);
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "uid")) {
630 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.uid = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "gid")) {
643 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.gid = atol(args[1]);
654 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200655 /* user/group name handling */
656 else if (!strcmp(args[0], "user")) {
657 struct passwd *ha_user;
658 if (global.uid != 0) {
659 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
661 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200662 }
663 errno = 0;
664 ha_user = getpwnam(args[1]);
665 if (ha_user != NULL) {
666 global.uid = (int)ha_user->pw_uid;
667 }
668 else {
669 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 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200671 }
672 }
673 else if (!strcmp(args[0], "group")) {
674 struct group *ha_group;
675 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200676 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200679 }
680 errno = 0;
681 ha_group = getgrnam(args[1]);
682 if (ha_group != NULL) {
683 global.gid = (int)ha_group->gr_gid;
684 }
685 else {
686 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 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200688 }
689 }
690 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 else if (!strcmp(args[0], "nbproc")) {
692 if (global.nbproc != 0) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.nbproc = atol(args[1]);
703 }
704 else if (!strcmp(args[0], "maxconn")) {
705 if (global.maxconn != 0) {
706 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT;
708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 }
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 }
715 global.maxconn = atol(args[1]);
716#ifdef SYSTEM_MAXCONN
717 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
718 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);
719 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200720 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722#endif /* SYSTEM_MAXCONN */
723 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200724 else if (!strcmp(args[0], "maxsslconn")) {
725#ifdef USE_OPENSSL
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.maxsslconn = atol(args[1]);
732#else
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#endif
739 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200740 else if (!strcmp(args[0], "maxconnrate")) {
741 if (global.cps_lim != 0) {
742 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT;
744 goto out;
745 }
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 global.cps_lim = atol(args[1]);
752 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100753 else if (!strcmp(args[0], "maxpipes")) {
754 if (global.maxpipes != 0) {
755 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
757 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100758 }
759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100763 }
764 global.maxpipes = atol(args[1]);
765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 else if (!strcmp(args[0], "ulimit-n")) {
767 if (global.rlimit_nofile != 0) {
768 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772 if (*(args[1]) == 0) {
773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 global.rlimit_nofile = atol(args[1]);
778 }
779 else if (!strcmp(args[0], "chroot")) {
780 if (global.chroot != NULL) {
781 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT;
783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 if (*(args[1]) == 0) {
786 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 global.chroot = strdup(args[1]);
791 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200792 else if (!strcmp(args[0], "description")) {
793 int i, len=0;
794 char *d;
795
796 if (!*args[1]) {
797 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802
803 for(i=1; *args[i]; i++)
804 len += strlen(args[i])+1;
805
806 if (global.desc)
807 free(global.desc);
808
809 global.desc = d = (char *)calloc(1, len);
810
811 d += sprintf(d, "%s", args[1]);
812 for(i=2; *args[i]; i++)
813 d += sprintf(d, " %s", args[i]);
814 }
815 else if (!strcmp(args[0], "node")) {
816 int i;
817 char c;
818
819 for (i=0; args[1][i]; i++) {
820 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100821 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
822 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200823 break;
824 }
825
826 if (!i || args[1][i]) {
827 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
828 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
829 file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833
834 if (global.node)
835 free(global.node);
836
837 global.node = strdup(args[1]);
838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 else if (!strcmp(args[0], "pidfile")) {
840 if (global.pidfile != NULL) {
841 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200842 err_code |= ERR_ALERT;
843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.pidfile = strdup(args[1]);
851 }
Emeric Bruned760922010-10-22 17:59:25 +0200852 else if (!strcmp(args[0], "unix-bind")) {
853 int cur_arg = 1;
854 while (*(args[cur_arg])) {
855 if (!strcmp(args[cur_arg], "prefix")) {
856 if (global.unix_bind.prefix != NULL) {
857 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
858 err_code |= ERR_ALERT;
859 cur_arg += 2;
860 continue;
861 }
862
863 if (*(args[cur_arg+1]) == 0) {
864 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868 global.unix_bind.prefix = strdup(args[cur_arg+1]);
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "mode")) {
874
875 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
876 cur_arg += 2;
877 continue;
878 }
879
880 if (!strcmp(args[cur_arg], "uid")) {
881
882 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
883 cur_arg += 2;
884 continue;
885 }
886
887 if (!strcmp(args[cur_arg], "gid")) {
888
889 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
890 cur_arg += 2;
891 continue;
892 }
893
894 if (!strcmp(args[cur_arg], "user")) {
895 struct passwd *user;
896
897 user = getpwnam(args[cur_arg + 1]);
898 if (!user) {
899 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
900 file, linenum, args[0], args[cur_arg + 1 ]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 global.unix_bind.ux.uid = user->pw_uid;
906 cur_arg += 2;
907 continue;
908 }
909
910 if (!strcmp(args[cur_arg], "group")) {
911 struct group *group;
912
913 group = getgrnam(args[cur_arg + 1]);
914 if (!group) {
915 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
916 file, linenum, args[0], args[cur_arg + 1 ]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920
921 global.unix_bind.ux.gid = group->gr_gid;
922 cur_arg += 2;
923 continue;
924 }
925
Willy Tarreaub48f9582011-09-05 01:17:06 +0200926 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200927 file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
William Lallemand0f99e342011-10-12 17:50:54 +0200932 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
933 /* delete previous herited or defined syslog servers */
934 struct logsrv *back;
935 struct logsrv *tmp;
936
937 if (*(args[1]) != 0) {
938 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942
943 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
944 LIST_DEL(&tmp->list);
945 free(tmp);
946 }
947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200949 struct logsrv *logsrv;
950
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (*(args[1]) == 0 || *(args[2]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
William Lallemand0f99e342011-10-12 17:50:54 +0200956
957 logsrv = calloc(1, sizeof(struct logsrv));
958
959 logsrv->facility = get_log_facility(args[2]);
960 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
965
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->level = get_log_level(args[3]);
969 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200972 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 }
975
William Lallemand0f99e342011-10-12 17:50:54 +0200976 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200977 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200978 logsrv->minlvl = get_log_level(args[4]);
979 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200980 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200982 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200983 }
984 }
985
Robert Tsai81ae1952007-12-05 10:47:29 +0100986 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100987 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100988 if (!sk) {
989 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100990 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100991 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200992 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100993 goto out;
994 }
William Lallemand0f99e342011-10-12 17:50:54 +0200995 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100996 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100997 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100998 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100999 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1000 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001001 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001002 goto out;
1003 }
William Lallemand0f99e342011-10-12 17:50:54 +02001004 logsrv->addr = *sk;
1005 if (!get_host_port(&logsrv->addr))
1006 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008
William Lallemand0f99e342011-10-12 17:50:54 +02001009 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001011 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1012 char *name;
1013 int len;
1014
1015 if (global.log_send_hostname != NULL) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT;
1018 goto out;
1019 }
1020
1021 if (*(args[1]))
1022 name = args[1];
1023 else
1024 name = hostname;
1025
1026 len = strlen(name);
1027
1028 /* We'll add a space after the name to respect the log format */
1029 free(global.log_send_hostname);
1030 global.log_send_hostname = malloc(len + 2);
1031 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1032 }
Kevinm48936af2010-12-22 16:08:21 +00001033 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1034 if (*(args[1]) == 0) {
1035 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 free(global.log_tag);
1040 global.log_tag = strdup(args[1]);
1041 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001042 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1043 if (global.spread_checks != 0) {
1044 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT;
1046 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001047 }
1048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001052 }
1053 global.spread_checks = atol(args[1]);
1054 if (global.spread_checks < 0 || global.spread_checks > 50) {
1055 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060 struct cfg_kw_list *kwl;
1061 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001062 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001063
1064 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1065 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1066 if (kwl->kw[index].section != CFG_GLOBAL)
1067 continue;
1068 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1069 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001070 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001071 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001072 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001073 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001074 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001076 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001077 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001078 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_WARN;
1080 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001081 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001082 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001083 }
1084 }
1085 }
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001090
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001092 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094}
1095
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001096void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001098 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 defproxy.mode = PR_MODE_TCP;
1100 defproxy.state = PR_STNEW;
1101 defproxy.maxconn = cfg_maxpconn;
1102 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001103
1104 defproxy.defsrv.inter = DEF_CHKINTR;
1105 defproxy.defsrv.fastinter = 0;
1106 defproxy.defsrv.downinter = 0;
1107 defproxy.defsrv.rise = DEF_RISETIME;
1108 defproxy.defsrv.fall = DEF_FALLTIME;
1109 defproxy.defsrv.check_port = 0;
1110 defproxy.defsrv.maxqueue = 0;
1111 defproxy.defsrv.minconn = 0;
1112 defproxy.defsrv.maxconn = 0;
1113 defproxy.defsrv.slowstart = 0;
1114 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1115 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1116 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117}
1118
Willy Tarreauade5ec42010-01-28 19:33:49 +01001119
1120static int create_cond_regex_rule(const char *file, int line,
1121 struct proxy *px, int dir, int action, int flags,
1122 const char *cmd, const char *reg, const char *repl,
1123 const char **cond_start)
1124{
1125 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001126 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127 const char *err;
1128 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001129 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001130
1131 if (px == &defproxy) {
1132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (*reg == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1144 err_code |= ERR_WARN;
1145
Willy Tarreau5321c422010-01-28 20:35:13 +01001146 if (cond_start &&
1147 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001148 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1149 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1150 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto err;
1153 }
1154 }
1155 else if (cond_start && **cond_start) {
1156 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1157 file, line, cmd, *cond_start);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto err;
1160 }
1161
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001162 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001163 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001164 else
1165 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001166
Willy Tarreauade5ec42010-01-28 19:33:49 +01001167 preg = calloc(1, sizeof(regex_t));
1168 if (!preg) {
1169 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1170 err_code = ERR_ALERT | ERR_FATAL;
1171 goto err;
1172 }
1173
1174 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1175 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1176 err_code = ERR_ALERT | ERR_FATAL;
1177 goto err;
1178 }
1179
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001180 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001181 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001182 if (repl && err) {
1183 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1184 file, line, cmd, *err);
1185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto err;
1187 }
1188
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001189 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001190 err_code |= ERR_WARN;
1191
Willy Tarreauf4068b62012-05-08 17:37:49 +02001192 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001193 return err_code;
1194 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001195 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001196 free(preg);
1197 return err_code;
1198}
1199
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001201 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001202 * Returns the error code, 0 if OK, or any combination of :
1203 * - ERR_ABORT: must abort ASAP
1204 * - ERR_FATAL: we can continue parsing but not start the service
1205 * - ERR_WARN: a warning has been emitted
1206 * - ERR_ALERT: an alert has been emitted
1207 * Only the two first ones can stop processing, the two others are just
1208 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001210int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1211{
1212 static struct peers *curpeers = NULL;
1213 struct peer *newpeer = NULL;
1214 const char *err;
1215 int err_code = 0;
1216
1217 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1218
1219 err = invalid_char(args[1]);
1220 if (err) {
1221 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1222 file, linenum, *err, args[0], args[1]);
1223 err_code |= ERR_ALERT | ERR_FATAL;
1224 }
1225
1226 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1227 /*
1228 * If there are two proxies with the same name only following
1229 * combinations are allowed:
1230 */
1231 if (strcmp(curpeers->id, args[1]) == 0) {
1232 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1233 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1234 err_code |= ERR_WARN;
1235 }
1236 }
1237
1238 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1240 err_code |= ERR_ALERT | ERR_ABORT;
1241 goto out;
1242 }
1243
1244 curpeers->next = peers;
1245 peers = curpeers;
1246 curpeers->conf.file = file;
1247 curpeers->conf.line = linenum;
1248 curpeers->last_change = now.tv_sec;
1249 curpeers->id = strdup(args[1]);
1250 }
1251 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1252 char *rport, *raddr;
1253 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001254 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001255
1256 if (!*args[2]) {
1257 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1258 file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 err = invalid_char(args[1]);
1264 if (err) {
1265 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1266 file, linenum, *err, args[1]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1273 err_code |= ERR_ALERT | ERR_ABORT;
1274 goto out;
1275 }
1276
1277 /* the peers are linked backwards first */
1278 curpeers->count++;
1279 newpeer->next = curpeers->remote;
1280 curpeers->remote = newpeer;
1281 newpeer->peers = curpeers;
1282 newpeer->conf.file = file;
1283 newpeer->conf.line = linenum;
1284
1285 newpeer->last_change = now.tv_sec;
1286 newpeer->id = strdup(args[1]);
1287
1288 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001289 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001290 if (rport) {
1291 *rport++ = 0;
1292 realport = atol(rport);
1293 }
1294 if (!realport) {
1295 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
Willy Tarreaufab5a432011-03-04 15:31:53 +01001300 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001301 free(raddr);
1302 if (!sk) {
1303 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001308 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001309 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001310 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001311
1312 if (!sk) {
1313 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1314 file, linenum, newpeer->addr.ss_family, args[2]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001319 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001320
1321 if (strcmp(newpeer->id, localpeer) == 0) {
1322 /* Current is local peer, it define a frontend */
1323 newpeer->local = 1;
1324
1325 if (!curpeers->peers_fe) {
1326 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1328 err_code |= ERR_ALERT | ERR_ABORT;
1329 goto out;
1330 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001331
Willy Tarreau237250c2011-07-29 01:49:03 +02001332 init_new_proxy(curpeers->peers_fe);
1333 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001334
1335 curpeers->peers_fe->last_change = now.tv_sec;
1336 curpeers->peers_fe->id = strdup(args[1]);
1337 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001338 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001339 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1340 curpeers->peers_fe->timeout.connect = 5000;
1341 curpeers->peers_fe->accept = peer_accept;
1342 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001343 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001344 err_code |= ERR_FATAL;
1345 goto out;
1346 }
1347 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1348 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1349 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1350 curpeers->peers_fe->listen->accept = session_accept;
1351 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1352 curpeers->peers_fe->listen->handler = process_session;
1353 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001354 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1355 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001356 }
1357 }
1358 } /* neither "peer" nor "peers" */
1359 else if (*args[0] != 0) {
1360 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363 }
1364
1365out:
1366 return err_code;
1367}
1368
1369
Willy Tarreau3842f002009-06-14 11:39:52 +02001370int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371{
1372 static struct proxy *curproxy = NULL;
1373 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001374 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001375 int rc;
1376 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001377 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001378 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001379 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001380 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001381 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382
Willy Tarreau977b8e42006-12-29 14:19:17 +01001383 if (!strcmp(args[0], "listen"))
1384 rc = PR_CAP_LISTEN;
1385 else if (!strcmp(args[0], "frontend"))
1386 rc = PR_CAP_FE | PR_CAP_RS;
1387 else if (!strcmp(args[0], "backend"))
1388 rc = PR_CAP_BE | PR_CAP_RS;
1389 else if (!strcmp(args[0], "ruleset"))
1390 rc = PR_CAP_RS;
1391 else
1392 rc = PR_CAP_NONE;
1393
1394 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 if (!*args[1]) {
1396 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1397 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001399 err_code |= ERR_ALERT | ERR_ABORT;
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001402
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001403 err = invalid_char(args[1]);
1404 if (err) {
1405 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1406 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001407 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001408 }
1409
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001410 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1411 /*
1412 * If there are two proxies with the same name only following
1413 * combinations are allowed:
1414 *
1415 * listen backend frontend ruleset
1416 * listen - - - -
1417 * backend - - OK -
1418 * frontend - OK - -
1419 * ruleset - - - -
1420 */
1421
1422 if (!strcmp(curproxy->id, args[1]) &&
1423 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1424 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001425 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1426 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1427 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001428 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001429 }
1430 }
1431
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1433 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001434 err_code |= ERR_ALERT | ERR_ABORT;
1435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001437
Willy Tarreau97cb7802010-01-03 20:23:58 +01001438 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 curproxy->next = proxy;
1440 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001441 curproxy->conf.file = file;
1442 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001443 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001445 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446
1447 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001448 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001449 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001450 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_FATAL;
1452 goto out;
1453 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001454 new = curproxy->listen;
1455 while (new != last) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001456 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001457 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 }
1460
1461 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001462 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001463 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001464
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001467 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001468 curproxy->no_options = defproxy.no_options;
1469 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001470 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001471 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001472 curproxy->except_net = defproxy.except_net;
1473 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001474 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001475 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001477 if (defproxy.fwdfor_hdr_len) {
1478 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1479 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1480 }
1481
Willy Tarreaub86db342009-11-30 11:50:16 +01001482 if (defproxy.orgto_hdr_len) {
1483 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1484 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1485 }
1486
Mark Lamourinec2247f02012-01-04 13:02:01 -05001487 if (defproxy.server_id_hdr_len) {
1488 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1489 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1490 }
1491
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (curproxy->cap & PR_CAP_FE) {
1493 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001494 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001495 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001496
1497 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001498 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1499 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001500
1501 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001503
Willy Tarreau977b8e42006-12-29 14:19:17 +01001504 if (curproxy->cap & PR_CAP_BE) {
1505 curproxy->fullconn = defproxy.fullconn;
1506 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001508 if (defproxy.check_req) {
1509 curproxy->check_req = calloc(1, defproxy.check_len);
1510 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1511 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001514 if (defproxy.expect_str) {
1515 curproxy->expect_str = strdup(defproxy.expect_str);
1516 if (defproxy.expect_regex) {
1517 /* note: this regex is known to be valid */
1518 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1519 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1520 }
1521 }
1522
Willy Tarreau67402132012-05-31 20:40:20 +02001523 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 if (defproxy.cookie_name)
1525 curproxy->cookie_name = strdup(defproxy.cookie_name);
1526 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001527 if (defproxy.cookie_domain)
1528 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001529
Willy Tarreau31936852010-10-06 16:59:56 +02001530 if (defproxy.cookie_maxidle)
1531 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1532
1533 if (defproxy.cookie_maxlife)
1534 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1535
Emeric Brun647caf12009-06-30 17:57:00 +02001536 if (defproxy.rdp_cookie_name)
1537 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1538 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1539
Willy Tarreau01732802007-11-01 22:48:15 +01001540 if (defproxy.url_param_name)
1541 curproxy->url_param_name = strdup(defproxy.url_param_name);
1542 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001543
Benoitaffb4812009-03-25 13:02:10 +01001544 if (defproxy.hh_name)
1545 curproxy->hh_name = strdup(defproxy.hh_name);
1546 curproxy->hh_len = defproxy.hh_len;
1547 curproxy->hh_match_domain = defproxy.hh_match_domain;
1548
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001549 if (defproxy.iface_name)
1550 curproxy->iface_name = strdup(defproxy.iface_name);
1551 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001554 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001555 if (defproxy.capture_name)
1556 curproxy->capture_name = strdup(defproxy.capture_name);
1557 curproxy->capture_namelen = defproxy.capture_namelen;
1558 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560
Willy Tarreau977b8e42006-12-29 14:19:17 +01001561 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001562 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001563 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001564 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001565 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566 curproxy->uri_auth = defproxy.uri_auth;
1567 curproxy->mon_net = defproxy.mon_net;
1568 curproxy->mon_mask = defproxy.mon_mask;
1569 if (defproxy.monitor_uri)
1570 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1571 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001572 if (defproxy.defbe.name)
1573 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001574
1575 /* get either a pointer to the logformat string or a copy of it */
1576 curproxy->logformat_string = defproxy.logformat_string;
1577 if (curproxy->logformat_string &&
1578 curproxy->logformat_string != default_http_log_format &&
1579 curproxy->logformat_string != default_tcp_log_format &&
1580 curproxy->logformat_string != clf_http_log_format)
1581 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001582 }
1583
1584 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001585 curproxy->timeout.connect = defproxy.timeout.connect;
1586 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001587 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001588 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001589 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001590 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001591 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001592 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001593 curproxy->source_addr = defproxy.source_addr;
1594 }
1595
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001597
1598 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001599 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001600 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001601 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001602 LIST_INIT(&node->list);
1603 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1604 }
1605
Willy Tarreau196729e2012-05-31 19:30:26 +02001606 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1607 if (curproxy->uniqueid_format_string)
1608 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001609
1610 /* copy default header unique id */
1611 if (defproxy.header_unique_id)
1612 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1613
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001615 curproxy->conf.used_listener_id = EB_ROOT;
1616 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001617
Willy Tarreau93893792009-07-23 13:19:11 +02001618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 }
1620 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1621 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001622 /* FIXME-20070101: we should do this too at the end of the
1623 * config parsing to free all default values.
1624 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001625 free(defproxy.check_req);
1626 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001627 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001628 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001629 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001630 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001631 free(defproxy.capture_name);
1632 free(defproxy.monitor_uri);
1633 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001634 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001635 free(defproxy.fwdfor_hdr_name);
1636 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001637 free(defproxy.orgto_hdr_name);
1638 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001639 free(defproxy.server_id_hdr_name);
1640 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001641 free(defproxy.expect_str);
1642 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001643
Willy Tarreau39b06652012-06-01 10:58:06 +02001644 if (defproxy.logformat_string != default_http_log_format &&
1645 defproxy.logformat_string != default_tcp_log_format &&
1646 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001647 free(defproxy.logformat_string);
1648
1649 free(defproxy.uniqueid_format_string);
1650
Willy Tarreaua534fea2008-08-03 12:19:50 +02001651 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001652 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001653
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 /* we cannot free uri_auth because it might already be used */
1655 init_default_instance();
1656 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001657 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 }
1660 else if (curproxy == NULL) {
1661 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
1665
Willy Tarreau977b8e42006-12-29 14:19:17 +01001666
1667 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001669 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001670 int cur_arg;
1671
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 if (curproxy == &defproxy) {
1673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001677 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001678 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679
Emeric Bruned760922010-10-22 17:59:25 +02001680 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001681 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001686
1687 last_listen = curproxy->listen;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001688 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8a956912010-10-15 14:27:08 +02001689
1690 /* NOTE: the following line might create several listeners if there
1691 * are comma-separated IPs or port ranges. So all further processing
1692 * will have to be applied to all listeners created after last_listen.
1693 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001694 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001698
Willy Tarreau90a570f2009-10-04 20:54:54 +02001699 new_listen = curproxy->listen;
1700 while (new_listen != last_listen) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001701 new_listen->bind_conf = bind_conf;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001702 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001703 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001704 }
1705
Emeric Bruned760922010-10-22 17:59:25 +02001706 /* Set default global rights and owner for unix bind */
1707 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1708 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1709 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001710 cur_arg = 2;
1711 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001712 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001713 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001714 char *err;
1715
Willy Tarreau26982662012-09-12 23:17:10 +02001716 kw = bind_find_kw(args[cur_arg]);
1717 if (kw) {
1718 char *err = NULL;
1719 int code;
1720
1721 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001722 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1723 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001724 cur_arg += 1 + kw->skip ;
1725 err_code |= ERR_ALERT | ERR_FATAL;
1726 goto out;
1727 }
1728
1729 code = kw->parse(args, cur_arg, curproxy, last_listen, &err);
1730 err_code |= code;
1731
1732 if (code) {
1733 if (err && *err) {
1734 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001735 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001736 }
1737 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001738 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1739 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001740 if (code & ERR_FATAL) {
1741 free(err);
1742 cur_arg += 1 + kw->skip;
1743 goto out;
1744 }
1745 }
1746 free(err);
1747 cur_arg += 1 + kw->skip;
1748 continue;
1749 }
1750
Willy Tarreau8638f482012-09-18 18:01:17 +02001751 err = NULL;
1752 if (!bind_dumped) {
1753 bind_dump_kws(&err);
1754 indent_msg(&err, 4);
1755 bind_dumped = 1;
1756 }
1757
1758 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1759 file, linenum, args[0], args[1], args[cur_arg],
1760 err ? " Registered keywords :" : "", err ? err : "");
1761 free(err);
1762
Willy Tarreau93893792009-07-23 13:19:11 +02001763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001765 }
Willy Tarreau93893792009-07-23 13:19:11 +02001766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 }
1768 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1769 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1770 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1771 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001776 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001777
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 /* flush useless bits */
1779 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001782 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001785
Willy Tarreau1c47f852006-07-09 08:22:27 +02001786 if (!*args[1]) {
1787 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1788 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001791 }
1792
Willy Tarreaua534fea2008-08-03 12:19:50 +02001793 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001794 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001795 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001796 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001797 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1798
Willy Tarreau93893792009-07-23 13:19:11 +02001799 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1802 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1803 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1804 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1805 else {
1806 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809 }
1810 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001811 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001812 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001813
1814 if (curproxy == &defproxy) {
1815 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1816 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001819 }
1820
1821 if (!*args[1]) {
1822 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1823 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001826 }
1827
1828 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001829 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001830
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001831 if (curproxy->uuid <= 0) {
1832 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001833 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001836 }
1837
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001838 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1839 if (node) {
1840 struct proxy *target = container_of(node, struct proxy, conf.id);
1841 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1842 file, linenum, proxy_type_str(curproxy), curproxy->id,
1843 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001848 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001849 else if (!strcmp(args[0], "description")) {
1850 int i, len=0;
1851 char *d;
1852
Cyril Bonté99ed3272010-01-24 23:29:44 +01001853 if (curproxy == &defproxy) {
1854 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1855 file, linenum, args[0]);
1856 err_code |= ERR_ALERT | ERR_FATAL;
1857 goto out;
1858 }
1859
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001860 if (!*args[1]) {
1861 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1862 file, linenum, args[0]);
1863 return -1;
1864 }
1865
1866 for(i=1; *args[i]; i++)
1867 len += strlen(args[i])+1;
1868
1869 d = (char *)calloc(1, len);
1870 curproxy->desc = d;
1871
1872 d += sprintf(d, "%s", args[1]);
1873 for(i=2; *args[i]; i++)
1874 d += sprintf(d, " %s", args[i]);
1875
1876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1878 curproxy->state = PR_STSTOPPED;
1879 }
1880 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1881 curproxy->state = PR_STNEW;
1882 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001883 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1884 int cur_arg = 1;
1885 unsigned int set = 0;
1886
1887 while (*args[cur_arg]) {
1888 int u;
1889 if (strcmp(args[cur_arg], "all") == 0) {
1890 set = 0;
1891 break;
1892 }
1893 else if (strcmp(args[cur_arg], "odd") == 0) {
1894 set |= 0x55555555;
1895 }
1896 else if (strcmp(args[cur_arg], "even") == 0) {
1897 set |= 0xAAAAAAAA;
1898 }
1899 else {
1900 u = str2uic(args[cur_arg]);
1901 if (u < 1 || u > 32) {
1902 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1903 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001906 }
1907 if (u > global.nbproc) {
1908 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1909 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001910 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001911 }
1912 set |= 1 << (u - 1);
1913 }
1914 cur_arg++;
1915 }
1916 curproxy->bind_proc = set;
1917 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001918 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001919 if (curproxy == &defproxy) {
1920 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001923 }
1924
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001925 err = invalid_char(args[1]);
1926 if (err) {
1927 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1928 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001930 }
1931
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001932 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
1933 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
1934 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001937 }
1938 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1940 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001944
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 if (*(args[1]) == 0) {
1946 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001951
Willy Tarreau67402132012-05-31 20:40:20 +02001952 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001953 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001954 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001955 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 curproxy->cookie_name = strdup(args[1]);
1957 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001958
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 cur_arg = 2;
1960 while (*(args[cur_arg])) {
1961 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001962 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 }
1964 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001965 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 }
1967 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001968 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 }
1970 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001971 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 }
1973 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001974 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001976 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001977 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001980 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02001982 else if (!strcmp(args[cur_arg], "httponly")) {
1983 curproxy->ck_opts |= PR_CK_HTTPONLY;
1984 }
1985 else if (!strcmp(args[cur_arg], "secure")) {
1986 curproxy->ck_opts |= PR_CK_SECURE;
1987 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001988 else if (!strcmp(args[cur_arg], "domain")) {
1989 if (!*args[cur_arg + 1]) {
1990 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1991 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001994 }
1995
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001996 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001997 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001998 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1999 " dots nor does not start with a dot."
2000 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002001 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002002 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002003 }
2004
2005 err = invalid_domainchar(args[cur_arg + 1]);
2006 if (err) {
2007 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2008 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002011 }
2012
Willy Tarreau68a897b2009-12-03 23:28:34 +01002013 if (!curproxy->cookie_domain) {
2014 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2015 } else {
2016 /* one domain was already specified, add another one by
2017 * building the string which will be returned along with
2018 * the cookie.
2019 */
2020 char *new_ptr;
2021 int new_len = strlen(curproxy->cookie_domain) +
2022 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2023 new_ptr = malloc(new_len);
2024 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2025 free(curproxy->cookie_domain);
2026 curproxy->cookie_domain = new_ptr;
2027 }
Willy Tarreau31936852010-10-06 16:59:56 +02002028 cur_arg++;
2029 }
2030 else if (!strcmp(args[cur_arg], "maxidle")) {
2031 unsigned int maxidle;
2032 const char *res;
2033
2034 if (!*args[cur_arg + 1]) {
2035 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2036 file, linenum, args[cur_arg]);
2037 err_code |= ERR_ALERT | ERR_FATAL;
2038 goto out;
2039 }
2040
2041 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2042 if (res) {
2043 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2044 file, linenum, *res, args[cur_arg]);
2045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
2047 }
2048 curproxy->cookie_maxidle = maxidle;
2049 cur_arg++;
2050 }
2051 else if (!strcmp(args[cur_arg], "maxlife")) {
2052 unsigned int maxlife;
2053 const char *res;
2054
2055 if (!*args[cur_arg + 1]) {
2056 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2057 file, linenum, args[cur_arg]);
2058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
2060 }
2061
2062 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2063 if (res) {
2064 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2065 file, linenum, *res, args[cur_arg]);
2066 err_code |= ERR_ALERT | ERR_FATAL;
2067 goto out;
2068 }
2069 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002070 cur_arg++;
2071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002073 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 +02002074 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 }
2078 cur_arg++;
2079 }
Willy Tarreau67402132012-05-31 20:40:20 +02002080 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2082 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 }
2085
Willy Tarreau67402132012-05-31 20:40:20 +02002086 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2088 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002091
Willy Tarreau67402132012-05-31 20:40:20 +02002092 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002093 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2094 file, linenum);
2095 err_code |= ERR_ALERT | ERR_FATAL;
2096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002098 else if (!strcmp(args[0], "persist")) { /* persist */
2099 if (*(args[1]) == 0) {
2100 Alert("parsing [%s:%d] : missing persist method.\n",
2101 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002104 }
2105
2106 if (!strncmp(args[1], "rdp-cookie", 10)) {
2107 curproxy->options2 |= PR_O2_RDPC_PRST;
2108
Emeric Brunb982a3d2010-01-04 15:45:53 +01002109 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002110 const char *beg, *end;
2111
2112 beg = args[1] + 11;
2113 end = strchr(beg, ')');
2114
2115 if (!end || end == beg) {
2116 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2117 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002118 err_code |= ERR_ALERT | ERR_FATAL;
2119 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002120 }
2121
2122 free(curproxy->rdp_cookie_name);
2123 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2124 curproxy->rdp_cookie_len = end-beg;
2125 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002126 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002127 free(curproxy->rdp_cookie_name);
2128 curproxy->rdp_cookie_name = strdup("msts");
2129 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2130 }
2131 else { /* syntax */
2132 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2133 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002136 }
2137 }
2138 else {
2139 Alert("parsing [%s:%d] : unknown persist method.\n",
2140 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002143 }
2144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002146 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002148 if (curproxy == &defproxy) {
2149 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
2152 }
2153
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002156
Willy Tarreaubaaee002006-06-26 02:48:02 +02002157 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002158 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 }
2163 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002164 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 curproxy->appsession_name = strdup(args[1]);
2166 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2167 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002168 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2169 if (err) {
2170 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2171 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_ALERT | ERR_FATAL;
2173 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002174 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002175 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002176
Willy Tarreau51041c72007-09-09 21:56:53 +02002177 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2178 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002179 err_code |= ERR_ALERT | ERR_ABORT;
2180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002182
2183 cur_arg = 6;
2184 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002185 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2186 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002187 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002188 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002189 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002190 } else if (!strcmp(args[cur_arg], "prefix")) {
2191 curproxy->options2 |= PR_O2_AS_PFX;
2192 } else if (!strcmp(args[cur_arg], "mode")) {
2193 if (!*args[cur_arg + 1]) {
2194 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2195 file, linenum, args[0], args[cur_arg]);
2196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
2198 }
2199
2200 cur_arg++;
2201 if (!strcmp(args[cur_arg], "query-string")) {
2202 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2203 curproxy->options2 |= PR_O2_AS_M_QS;
2204 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2205 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2206 curproxy->options2 |= PR_O2_AS_M_PP;
2207 } else {
2208 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
2211 }
2212 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002213 cur_arg++;
2214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 } /* Url App Session */
2216 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002217 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002219
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002221 if (curproxy == &defproxy) {
2222 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 if (*(args[4]) == 0) {
2228 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2229 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002233 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 curproxy->capture_name = strdup(args[2]);
2235 curproxy->capture_namelen = strlen(curproxy->capture_name);
2236 curproxy->capture_len = atol(args[4]);
2237 if (curproxy->capture_len >= CAPTURE_LEN) {
2238 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2239 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 curproxy->capture_len = CAPTURE_LEN - 1;
2242 }
2243 curproxy->to_log |= LW_COOKIE;
2244 }
2245 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2246 struct cap_hdr *hdr;
2247
2248 if (curproxy == &defproxy) {
2249 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 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 }
2253
2254 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2255 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2256 file, linenum, args[0], args[1]);
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
2261 hdr = calloc(sizeof(struct cap_hdr), 1);
2262 hdr->next = curproxy->req_cap;
2263 hdr->name = strdup(args[3]);
2264 hdr->namelen = strlen(args[3]);
2265 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002266 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 hdr->index = curproxy->nb_req_cap++;
2268 curproxy->req_cap = hdr;
2269 curproxy->to_log |= LW_REQHDR;
2270 }
2271 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2272 struct cap_hdr *hdr;
2273
2274 if (curproxy == &defproxy) {
2275 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 +02002276 err_code |= ERR_ALERT | ERR_FATAL;
2277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 }
2279
2280 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2281 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2282 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 hdr = calloc(sizeof(struct cap_hdr), 1);
2287 hdr->next = curproxy->rsp_cap;
2288 hdr->name = strdup(args[3]);
2289 hdr->namelen = strlen(args[3]);
2290 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002291 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 hdr->index = curproxy->nb_rsp_cap++;
2293 curproxy->rsp_cap = hdr;
2294 curproxy->to_log |= LW_RSPHDR;
2295 }
2296 else {
2297 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
2302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002304 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002306
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307 if (*(args[1]) == 0) {
2308 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2309 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 }
2313 curproxy->conn_retries = atol(args[1]);
2314 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002315 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002316 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002317
2318 if (curproxy == &defproxy) {
2319 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323
Willy Tarreauff011f22011-01-06 17:51:27 +01002324 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 +01002325 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2326 file, linenum, args[0]);
2327 err_code |= ERR_WARN;
2328 }
2329
Willy Tarreauff011f22011-01-06 17:51:27 +01002330 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002331
Willy Tarreauff011f22011-01-06 17:51:27 +01002332 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002333 err_code |= ERR_ALERT | ERR_ABORT;
2334 goto out;
2335 }
2336
Willy Tarreauff011f22011-01-06 17:51:27 +01002337 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2338 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002339 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002340 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2341 /* set the header name and length into the proxy structure */
2342 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2343 err_code |= ERR_WARN;
2344
2345 if (!*args[1]) {
2346 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2347 file, linenum, args[0]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351
2352 /* set the desired header name */
2353 free(curproxy->server_id_hdr_name);
2354 curproxy->server_id_hdr_name = strdup(args[1]);
2355 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2356 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002357 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002358 if (curproxy == &defproxy) {
2359 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002362 }
2363
Willy Tarreauef6494c2010-01-28 17:12:36 +01002364 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002365 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2366 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002369 }
2370
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002371 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2372 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2373 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002376 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002377
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002378 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002379 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002380 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002381 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002382 struct redirect_rule *rule;
2383 int cur_arg;
2384 int type = REDIRECT_TYPE_NONE;
2385 int code = 302;
2386 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002387 char *cookie = NULL;
2388 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002389 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002390
Cyril Bonté99ed3272010-01-24 23:29:44 +01002391 if (curproxy == &defproxy) {
2392 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
2395 }
2396
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002397 cur_arg = 1;
2398 while (*(args[cur_arg])) {
2399 if (!strcmp(args[cur_arg], "location")) {
2400 if (!*args[cur_arg + 1]) {
2401 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2402 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002405 }
2406
2407 type = REDIRECT_TYPE_LOCATION;
2408 cur_arg++;
2409 destination = args[cur_arg];
2410 }
2411 else if (!strcmp(args[cur_arg], "prefix")) {
2412 if (!*args[cur_arg + 1]) {
2413 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2414 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002417 }
2418
2419 type = REDIRECT_TYPE_PREFIX;
2420 cur_arg++;
2421 destination = args[cur_arg];
2422 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002423 else if (!strcmp(args[cur_arg], "scheme")) {
2424 if (!*args[cur_arg + 1]) {
2425 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2426 file, linenum, args[0], args[cur_arg]);
2427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
2429 }
2430
2431 type = REDIRECT_TYPE_SCHEME;
2432 cur_arg++;
2433 destination = args[cur_arg];
2434 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002435 else if (!strcmp(args[cur_arg], "set-cookie")) {
2436 if (!*args[cur_arg + 1]) {
2437 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2438 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002441 }
2442
2443 cur_arg++;
2444 cookie = args[cur_arg];
2445 cookie_set = 1;
2446 }
2447 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2448 if (!*args[cur_arg + 1]) {
2449 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2450 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002453 }
2454
2455 cur_arg++;
2456 cookie = args[cur_arg];
2457 cookie_set = 0;
2458 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002459 else if (!strcmp(args[cur_arg],"code")) {
2460 if (!*args[cur_arg + 1]) {
2461 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2462 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002465 }
2466 cur_arg++;
2467 code = atol(args[cur_arg]);
2468 if (code < 301 || code > 303) {
2469 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2470 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002473 }
2474 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002475 else if (!strcmp(args[cur_arg],"drop-query")) {
2476 flags |= REDIRECT_FLAG_DROP_QS;
2477 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002478 else if (!strcmp(args[cur_arg],"append-slash")) {
2479 flags |= REDIRECT_FLAG_APPEND_SLASH;
2480 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002481 else if (strcmp(args[cur_arg], "if") == 0 ||
2482 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002483 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002484 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002485 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2486 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002490 break;
2491 }
2492 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002493 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002494 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002497 }
2498 cur_arg++;
2499 }
2500
2501 if (type == REDIRECT_TYPE_NONE) {
2502 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002506 }
2507
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002508 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2509 rule->cond = cond;
2510 rule->rdr_str = strdup(destination);
2511 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002512 if (cookie) {
2513 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002514 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002515 */
2516 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002517 if (cookie_set) {
2518 rule->cookie_str = malloc(rule->cookie_len + 10);
2519 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2520 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2521 rule->cookie_len += 9;
2522 } else {
2523 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002524 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002525 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2526 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002527 }
2528 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002529 rule->type = type;
2530 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002531 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002532 LIST_INIT(&rule->list);
2533 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002534 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2535 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002536 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002537 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002538 struct switching_rule *rule;
2539
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 Tarreau55ea7572007-06-17 19:56:27 +02002546 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002548
2549 if (*(args[1]) == 0) {
2550 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002553 }
2554
Willy Tarreauef6494c2010-01-28 17:12:36 +01002555 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002556 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002560 }
2561
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002562 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2563 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2564 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002567 }
2568
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002569 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002570
Willy Tarreau55ea7572007-06-17 19:56:27 +02002571 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2572 rule->cond = cond;
2573 rule->be.name = strdup(args[1]);
2574 LIST_INIT(&rule->list);
2575 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2576 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002577 else if (strcmp(args[0], "use-server") == 0) {
2578 struct server_rule *rule;
2579
2580 if (curproxy == &defproxy) {
2581 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2582 err_code |= ERR_ALERT | ERR_FATAL;
2583 goto out;
2584 }
2585
2586 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2587 err_code |= ERR_WARN;
2588
2589 if (*(args[1]) == 0) {
2590 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
2593 }
2594
2595 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2596 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2597 file, linenum, args[0]);
2598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
2600 }
2601
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002602 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2603 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2604 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
2607 }
2608
2609 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2610
2611 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2612 rule->cond = cond;
2613 rule->srv.name = strdup(args[1]);
2614 LIST_INIT(&rule->list);
2615 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2616 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2617 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002618 else if ((!strcmp(args[0], "force-persist")) ||
2619 (!strcmp(args[0], "ignore-persist"))) {
2620 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002621
2622 if (curproxy == &defproxy) {
2623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627
2628 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2629 err_code |= ERR_WARN;
2630
Willy Tarreauef6494c2010-01-28 17:12:36 +01002631 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002632 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2633 file, linenum, args[0]);
2634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
2636 }
2637
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002638 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2639 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2640 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002645 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002646
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002647 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002648 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002649 if (!strcmp(args[0], "force-persist")) {
2650 rule->type = PERSIST_TYPE_FORCE;
2651 } else {
2652 rule->type = PERSIST_TYPE_IGNORE;
2653 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002654 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002655 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002656 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002657 else if (!strcmp(args[0], "stick-table")) {
2658 int myidx = 1;
2659
Emeric Brun32da3c42010-09-23 18:39:19 +02002660 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002661 curproxy->table.type = (unsigned int)-1;
2662 while (*args[myidx]) {
2663 const char *err;
2664
2665 if (strcmp(args[myidx], "size") == 0) {
2666 myidx++;
2667 if (!*(args[myidx])) {
2668 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2669 file, linenum, args[myidx-1]);
2670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2674 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2675 file, linenum, *err, args[myidx-1]);
2676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
2678 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002679 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002680 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002681 else if (strcmp(args[myidx], "peers") == 0) {
2682 myidx++;
2683 if (!*(args[myidx])) {
2684 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2685 file, linenum, args[myidx-1]);
2686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
2689 curproxy->table.peers.name = strdup(args[myidx++]);
2690 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002691 else if (strcmp(args[myidx], "expire") == 0) {
2692 myidx++;
2693 if (!*(args[myidx])) {
2694 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2695 file, linenum, args[myidx-1]);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2700 if (err) {
2701 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2702 file, linenum, *err, args[myidx-1]);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
2706 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002707 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002708 }
2709 else if (strcmp(args[myidx], "nopurge") == 0) {
2710 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002711 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002712 }
2713 else if (strcmp(args[myidx], "type") == 0) {
2714 myidx++;
2715 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2716 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2717 file, linenum, args[myidx]);
2718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
2720 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002721 /* myidx already points to next arg */
2722 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002723 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002724 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002725 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002726
2727 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002728 nw = args[myidx];
2729 while (*nw) {
2730 /* the "store" keyword supports a comma-separated list */
2731 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002732 sa = NULL; /* store arg */
2733 while (*nw && *nw != ',') {
2734 if (*nw == '(') {
2735 *nw = 0;
2736 sa = ++nw;
2737 while (*nw != ')') {
2738 if (!*nw) {
2739 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2740 file, linenum, args[0], cw);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744 nw++;
2745 }
2746 *nw = '\0';
2747 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002748 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002749 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002750 if (*nw)
2751 *nw++ = '\0';
2752 type = stktable_get_data_type(cw);
2753 if (type < 0) {
2754 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2755 file, linenum, args[0], cw);
2756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
2758 }
Willy Tarreauac782882010-06-20 10:41:54 +02002759
2760 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2761 switch (err) {
2762 case PE_NONE: break;
2763 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002764 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2765 file, linenum, args[0], cw);
2766 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002767 break;
2768
2769 case PE_ARG_MISSING:
2770 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2771 file, linenum, args[0], cw);
2772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
2774
2775 case PE_ARG_NOT_USED:
2776 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2777 file, linenum, args[0], cw);
2778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
2780
2781 default:
2782 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2783 file, linenum, args[0], cw);
2784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002786 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002787 }
2788 myidx++;
2789 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002790 else {
2791 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2792 file, linenum, args[myidx]);
2793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002795 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002796 }
2797
2798 if (!curproxy->table.size) {
2799 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2800 file, linenum);
2801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
2803 }
2804
2805 if (curproxy->table.type == (unsigned int)-1) {
2806 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2807 file, linenum);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
2810 }
2811 }
2812 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002813 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002814 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002815 int myidx = 0;
2816 const char *name = NULL;
2817 int flags;
2818
2819 if (curproxy == &defproxy) {
2820 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
2823 }
2824
2825 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2826 err_code |= ERR_WARN;
2827 goto out;
2828 }
2829
2830 myidx++;
2831 if ((strcmp(args[myidx], "store") == 0) ||
2832 (strcmp(args[myidx], "store-request") == 0)) {
2833 myidx++;
2834 flags = STK_IS_STORE;
2835 }
2836 else if (strcmp(args[myidx], "store-response") == 0) {
2837 myidx++;
2838 flags = STK_IS_STORE | STK_ON_RSP;
2839 }
2840 else if (strcmp(args[myidx], "match") == 0) {
2841 myidx++;
2842 flags = STK_IS_MATCH;
2843 }
2844 else if (strcmp(args[myidx], "on") == 0) {
2845 myidx++;
2846 flags = STK_IS_MATCH | STK_IS_STORE;
2847 }
2848 else {
2849 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853
2854 if (*(args[myidx]) == 0) {
2855 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859
David du Colombier7af46052012-05-16 14:16:48 +02002860 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002861 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002862 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
2865 }
2866
2867 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002868 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002869 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2870 file, linenum, args[0], expr->fetch->kw);
2871 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002872 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002873 goto out;
2874 }
2875 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002876 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002877 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2878 file, linenum, args[0], expr->fetch->kw);
2879 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002880 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002881 goto out;
2882 }
2883 }
2884
2885 if (strcmp(args[myidx], "table") == 0) {
2886 myidx++;
2887 name = args[myidx++];
2888 }
2889
Willy Tarreauef6494c2010-01-28 17:12:36 +01002890 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002891 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2892 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2893 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002894 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002895 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002896 goto out;
2897 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002898 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002899 else if (*(args[myidx])) {
2900 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2901 file, linenum, args[0], args[myidx]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002903 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002904 goto out;
2905 }
Emeric Brun97679e72010-09-23 17:56:44 +02002906 if (flags & STK_ON_RSP)
2907 err_code |= warnif_cond_requires_req(cond, file, linenum);
2908 else
2909 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002910
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2912 rule->cond = cond;
2913 rule->expr = expr;
2914 rule->flags = flags;
2915 rule->table.name = name ? strdup(name) : NULL;
2916 LIST_INIT(&rule->list);
2917 if (flags & STK_ON_RSP)
2918 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2919 else
2920 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2921 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002923 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2927 curproxy->uri_auth = NULL; /* we must detach from the default config */
2928
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002929 if (!*args[1]) {
2930 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002931 } else if (!strcmp(args[1], "admin")) {
2932 struct stats_admin_rule *rule;
2933
2934 if (curproxy == &defproxy) {
2935 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
2939
2940 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2941 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2942 err_code |= ERR_ALERT | ERR_ABORT;
2943 goto out;
2944 }
2945
2946 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2947 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2948 file, linenum, args[0], args[1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002952 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2953 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
2954 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958
2959 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2960
2961 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2962 rule->cond = cond;
2963 LIST_INIT(&rule->list);
2964 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 } else if (!strcmp(args[1], "uri")) {
2966 if (*(args[2]) == 0) {
2967 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2971 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002972 err_code |= ERR_ALERT | ERR_ABORT;
2973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 }
2975 } else if (!strcmp(args[1], "realm")) {
2976 if (*(args[2]) == 0) {
2977 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2981 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_ALERT | ERR_ABORT;
2983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002985 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002986 unsigned interval;
2987
2988 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2989 if (err) {
2990 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2991 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002994 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2995 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_ABORT;
2997 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002998 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002999 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003000 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003001
3002 if (curproxy == &defproxy) {
3003 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3009 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3010 err_code |= ERR_ALERT | ERR_ABORT;
3011 goto out;
3012 }
3013
Willy Tarreauff011f22011-01-06 17:51:27 +01003014 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3015 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003016 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3017 file, linenum, args[0]);
3018 err_code |= ERR_WARN;
3019 }
3020
Willy Tarreauff011f22011-01-06 17:51:27 +01003021 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003022
Willy Tarreauff011f22011-01-06 17:51:27 +01003023 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003024 err_code |= ERR_ALERT | ERR_ABORT;
3025 goto out;
3026 }
3027
Willy Tarreauff011f22011-01-06 17:51:27 +01003028 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3029 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003030
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 } else if (!strcmp(args[1], "auth")) {
3032 if (*(args[2]) == 0) {
3033 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3037 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_ABORT;
3039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
3041 } else if (!strcmp(args[1], "scope")) {
3042 if (*(args[2]) == 0) {
3043 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_ABORT;
3049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
3051 } else if (!strcmp(args[1], "enable")) {
3052 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3053 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_ABORT;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003057 } else if (!strcmp(args[1], "hide-version")) {
3058 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3059 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_ABORT;
3061 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003062 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003063 } else if (!strcmp(args[1], "show-legends")) {
3064 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3065 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3066 err_code |= ERR_ALERT | ERR_ABORT;
3067 goto out;
3068 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003069 } else if (!strcmp(args[1], "show-node")) {
3070
3071 if (*args[2]) {
3072 int i;
3073 char c;
3074
3075 for (i=0; args[2][i]; i++) {
3076 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003077 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3078 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003079 break;
3080 }
3081
3082 if (!i || args[2][i]) {
3083 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3084 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3085 file, linenum, args[0], args[1]);
3086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
3088 }
3089 }
3090
3091 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3092 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3093 err_code |= ERR_ALERT | ERR_ABORT;
3094 goto out;
3095 }
3096 } else if (!strcmp(args[1], "show-desc")) {
3097 char *desc = NULL;
3098
3099 if (*args[2]) {
3100 int i, len=0;
3101 char *d;
3102
3103 for(i=2; *args[i]; i++)
3104 len += strlen(args[i])+1;
3105
3106 desc = d = (char *)calloc(1, len);
3107
3108 d += sprintf(d, "%s", args[2]);
3109 for(i=3; *args[i]; i++)
3110 d += sprintf(d, " %s", args[i]);
3111 }
3112
3113 if (!*args[2] && !global.desc)
3114 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3115 file, linenum, args[1]);
3116 else {
3117 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3118 free(desc);
3119 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3120 err_code |= ERR_ALERT | ERR_ABORT;
3121 goto out;
3122 }
3123 free(desc);
3124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003126stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003127 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 +01003128 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
3132 }
3133 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003134 int optnum;
3135
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003136 if (*(args[1]) == '\0') {
3137 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3138 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003142
3143 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3144 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003145 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3146 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3147 file, linenum, cfg_opts[optnum].name);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
Willy Tarreau93893792009-07-23 13:19:11 +02003151 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3152 err_code |= ERR_WARN;
3153 goto out;
3154 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003155
Willy Tarreau3842f002009-06-14 11:39:52 +02003156 curproxy->no_options &= ~cfg_opts[optnum].val;
3157 curproxy->options &= ~cfg_opts[optnum].val;
3158
3159 switch (kwm) {
3160 case KWM_STD:
3161 curproxy->options |= cfg_opts[optnum].val;
3162 break;
3163 case KWM_NO:
3164 curproxy->no_options |= cfg_opts[optnum].val;
3165 break;
3166 case KWM_DEF: /* already cleared */
3167 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003168 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003169
Willy Tarreau93893792009-07-23 13:19:11 +02003170 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003171 }
3172 }
3173
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003174 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3175 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003176 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3177 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3178 file, linenum, cfg_opts2[optnum].name);
3179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
3181 }
Willy Tarreau93893792009-07-23 13:19:11 +02003182 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3183 err_code |= ERR_WARN;
3184 goto out;
3185 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003186
Willy Tarreau3842f002009-06-14 11:39:52 +02003187 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3188 curproxy->options2 &= ~cfg_opts2[optnum].val;
3189
3190 switch (kwm) {
3191 case KWM_STD:
3192 curproxy->options2 |= cfg_opts2[optnum].val;
3193 break;
3194 case KWM_NO:
3195 curproxy->no_options2 |= cfg_opts2[optnum].val;
3196 break;
3197 case KWM_DEF: /* already cleared */
3198 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003199 }
Willy Tarreau93893792009-07-23 13:19:11 +02003200 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003201 }
3202 }
3203
Willy Tarreau3842f002009-06-14 11:39:52 +02003204 if (kwm != KWM_STD) {
3205 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003206 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003209 }
3210
Emeric Brun3a058f32009-06-30 18:26:00 +02003211 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003212 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003214 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003215 if (*(args[2]) != '\0') {
3216 if (!strcmp(args[2], "clf")) {
3217 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003218 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003219 } else {
3220 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003223 }
3224 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003225 if (curproxy->logformat_string != default_http_log_format &&
3226 curproxy->logformat_string != default_tcp_log_format &&
3227 curproxy->logformat_string != clf_http_log_format)
3228 free(curproxy->logformat_string);
3229 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003230 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003231 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003233 if (curproxy->logformat_string != default_http_log_format &&
3234 curproxy->logformat_string != default_tcp_log_format &&
3235 curproxy->logformat_string != clf_http_log_format)
3236 free(curproxy->logformat_string);
3237 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 else if (!strcmp(args[1], "tcpka")) {
3240 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003241 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003243
3244 if (curproxy->cap & PR_CAP_FE)
3245 curproxy->options |= PR_O_TCP_CLI_KA;
3246 if (curproxy->cap & PR_CAP_BE)
3247 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 }
3249 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003250 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_WARN;
3252
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003254 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003255 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003256 curproxy->options2 &= ~PR_O2_CHK_ANY;
3257 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 if (!*args[2]) { /* no argument */
3259 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3260 curproxy->check_len = strlen(DEF_CHECK_REQ);
3261 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003262 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 curproxy->check_req = (char *)malloc(reqlen);
3264 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003265 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003267 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 if (*args[4])
3269 reqlen += strlen(args[4]);
3270 else
3271 reqlen += strlen("HTTP/1.0");
3272
3273 curproxy->check_req = (char *)malloc(reqlen);
3274 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003275 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003277 }
3278 else if (!strcmp(args[1], "ssl-hello-chk")) {
3279 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003280 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003282
Willy Tarreaua534fea2008-08-03 12:19:50 +02003283 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003284 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003285 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003286 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 }
Willy Tarreau23677902007-05-08 23:50:35 +02003288 else if (!strcmp(args[1], "smtpchk")) {
3289 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003290 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003291 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003292 curproxy->options2 &= ~PR_O2_CHK_ANY;
3293 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003294
3295 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3296 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3297 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3298 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3299 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3300 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3301 curproxy->check_req = (char *)malloc(reqlen);
3302 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3303 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3304 } else {
3305 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3306 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3307 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3308 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3309 }
3310 }
3311 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003312 else if (!strcmp(args[1], "pgsql-check")) {
3313 /* use PostgreSQL request to check servers' health */
3314 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3315 err_code |= ERR_WARN;
3316
3317 free(curproxy->check_req);
3318 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003319 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003320 curproxy->options2 |= PR_O2_PGSQL_CHK;
3321
3322 if (*(args[2])) {
3323 int cur_arg = 2;
3324
3325 while (*(args[cur_arg])) {
3326 if (strcmp(args[cur_arg], "user") == 0) {
3327 char * packet;
3328 uint32_t packet_len;
3329 uint32_t pv;
3330
3331 /* suboption header - needs additional argument for it */
3332 if (*(args[cur_arg+1]) == 0) {
3333 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3334 file, linenum, args[0], args[1], args[cur_arg]);
3335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
3337 }
3338
3339 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3340 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3341 pv = htonl(0x30000); /* protocol version 3.0 */
3342
3343 packet = (char*) calloc(1, packet_len);
3344
3345 memcpy(packet + 4, &pv, 4);
3346
3347 /* copy "user" */
3348 memcpy(packet + 8, "user", 4);
3349
3350 /* copy username */
3351 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3352
3353 free(curproxy->check_req);
3354 curproxy->check_req = packet;
3355 curproxy->check_len = packet_len;
3356
3357 packet_len = htonl(packet_len);
3358 memcpy(packet, &packet_len, 4);
3359 cur_arg += 2;
3360 } else {
3361 /* unknown suboption - catchall */
3362 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3363 file, linenum, args[0], args[1]);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
3367 } /* end while loop */
3368 }
3369 }
3370
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003371 else if (!strcmp(args[1], "redis-check")) {
3372 /* use REDIS PING request to check servers' health */
3373 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3374 err_code |= ERR_WARN;
3375
3376 free(curproxy->check_req);
3377 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003378 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003379 curproxy->options2 |= PR_O2_REDIS_CHK;
3380
3381 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3382 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3383 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3384 }
3385
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003386 else if (!strcmp(args[1], "mysql-check")) {
3387 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003388 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3389 err_code |= ERR_WARN;
3390
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003391 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003392 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003393 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003394 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003395
3396 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3397 * const char mysql40_client_auth_pkt[] = {
3398 * "\x0e\x00\x00" // packet length
3399 * "\x01" // packet number
3400 * "\x00\x00" // client capabilities
3401 * "\x00\x00\x01" // max packet
3402 * "haproxy\x00" // username (null terminated string)
3403 * "\x00" // filler (always 0x00)
3404 * "\x01\x00\x00" // packet length
3405 * "\x00" // packet number
3406 * "\x01" // COM_QUIT command
3407 * };
3408 */
3409
3410 if (*(args[2])) {
3411 int cur_arg = 2;
3412
3413 while (*(args[cur_arg])) {
3414 if (strcmp(args[cur_arg], "user") == 0) {
3415 char *mysqluser;
3416 int packetlen, reqlen, userlen;
3417
3418 /* suboption header - needs additional argument for it */
3419 if (*(args[cur_arg+1]) == 0) {
3420 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3421 file, linenum, args[0], args[1], args[cur_arg]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425 mysqluser = args[cur_arg + 1];
3426 userlen = strlen(mysqluser);
3427 packetlen = userlen + 7;
3428 reqlen = packetlen + 9;
3429
3430 free(curproxy->check_req);
3431 curproxy->check_req = (char *)calloc(1, reqlen);
3432 curproxy->check_len = reqlen;
3433
3434 snprintf(curproxy->check_req, 4, "%c%c%c",
3435 ((unsigned char) packetlen & 0xff),
3436 ((unsigned char) (packetlen >> 8) & 0xff),
3437 ((unsigned char) (packetlen >> 16) & 0xff));
3438
3439 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003440 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003441 curproxy->check_req[8] = 1;
3442 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3443 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3444 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3445 cur_arg += 2;
3446 } else {
3447 /* unknown suboption - catchall */
3448 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3449 file, linenum, args[0], args[1]);
3450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
3452 }
3453 } /* end while loop */
3454 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003455 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003456 else if (!strcmp(args[1], "ldap-check")) {
3457 /* use LDAP request to check servers' health */
3458 free(curproxy->check_req);
3459 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003460 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003461 curproxy->options2 |= PR_O2_LDAP_CHK;
3462
3463 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3464 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3465 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3466 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003467 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003468 int cur_arg;
3469
3470 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3471 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003472 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003473
Willy Tarreau87cf5142011-08-19 22:57:24 +02003474 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003475
3476 free(curproxy->fwdfor_hdr_name);
3477 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3478 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3479
3480 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3481 cur_arg = 2;
3482 while (*(args[cur_arg])) {
3483 if (!strcmp(args[cur_arg], "except")) {
3484 /* suboption except - needs additional argument for it */
3485 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3486 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3487 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003490 }
3491 /* flush useless bits */
3492 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003493 cur_arg += 2;
3494 } else if (!strcmp(args[cur_arg], "header")) {
3495 /* suboption header - needs additional argument for it */
3496 if (*(args[cur_arg+1]) == 0) {
3497 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3498 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003501 }
3502 free(curproxy->fwdfor_hdr_name);
3503 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3504 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3505 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003506 } else if (!strcmp(args[cur_arg], "if-none")) {
3507 curproxy->options &= ~PR_O_FF_ALWAYS;
3508 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003509 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003510 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003511 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003512 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003515 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003516 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003517 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003518 else if (!strcmp(args[1], "originalto")) {
3519 int cur_arg;
3520
3521 /* insert x-original-to field, but not for the IP address listed as an except.
3522 * set default options (ie: bitfield, header name, etc)
3523 */
3524
3525 curproxy->options |= PR_O_ORGTO;
3526
3527 free(curproxy->orgto_hdr_name);
3528 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3529 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3530
Willy Tarreau87cf5142011-08-19 22:57:24 +02003531 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003532 cur_arg = 2;
3533 while (*(args[cur_arg])) {
3534 if (!strcmp(args[cur_arg], "except")) {
3535 /* suboption except - needs additional argument for it */
3536 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3537 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3538 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003541 }
3542 /* flush useless bits */
3543 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3544 cur_arg += 2;
3545 } else if (!strcmp(args[cur_arg], "header")) {
3546 /* suboption header - needs additional argument for it */
3547 if (*(args[cur_arg+1]) == 0) {
3548 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3549 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003552 }
3553 free(curproxy->orgto_hdr_name);
3554 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3555 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3556 cur_arg += 2;
3557 } else {
3558 /* unknown suboption - catchall */
3559 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3560 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003563 }
3564 } /* end while loop */
3565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 else {
3567 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 }
Willy Tarreau93893792009-07-23 13:19:11 +02003571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003573 else if (!strcmp(args[0], "default_backend")) {
3574 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003576
3577 if (*(args[1]) == 0) {
3578 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003581 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003582 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003583 curproxy->defbe.name = strdup(args[1]);
3584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003586 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003588
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003589 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3590 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 /* enable reconnections to dispatch */
3593 curproxy->options |= PR_O_REDISP;
3594 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003595 else if (!strcmp(args[0], "http-check")) {
3596 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003598
3599 if (strcmp(args[1], "disable-on-404") == 0) {
3600 /* enable a graceful server shutdown on an HTTP 404 response */
3601 curproxy->options |= PR_O_DISABLE404;
3602 }
Willy Tarreauef781042010-01-27 11:53:01 +01003603 else if (strcmp(args[1], "send-state") == 0) {
3604 /* enable emission of the apparent state of a server in HTTP checks */
3605 curproxy->options2 |= PR_O2_CHK_SNDST;
3606 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003607 else if (strcmp(args[1], "expect") == 0) {
3608 const char *ptr_arg;
3609 int cur_arg;
3610
3611 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3612 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616
3617 cur_arg = 2;
3618 /* consider exclamation marks, sole or at the beginning of a word */
3619 while (*(ptr_arg = args[cur_arg])) {
3620 while (*ptr_arg == '!') {
3621 curproxy->options2 ^= PR_O2_EXP_INV;
3622 ptr_arg++;
3623 }
3624 if (*ptr_arg)
3625 break;
3626 cur_arg++;
3627 }
3628 /* now ptr_arg points to the beginning of a word past any possible
3629 * exclamation mark, and cur_arg is the argument which holds this word.
3630 */
3631 if (strcmp(ptr_arg, "status") == 0) {
3632 if (!*(args[cur_arg + 1])) {
3633 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3634 file, linenum, args[0], args[1], ptr_arg);
3635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
3637 }
3638 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003639 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003640 curproxy->expect_str = strdup(args[cur_arg + 1]);
3641 }
3642 else if (strcmp(ptr_arg, "string") == 0) {
3643 if (!*(args[cur_arg + 1])) {
3644 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3645 file, linenum, args[0], args[1], ptr_arg);
3646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
3648 }
3649 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003650 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003651 curproxy->expect_str = strdup(args[cur_arg + 1]);
3652 }
3653 else if (strcmp(ptr_arg, "rstatus") == 0) {
3654 if (!*(args[cur_arg + 1])) {
3655 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3656 file, linenum, args[0], args[1], ptr_arg);
3657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
3659 }
3660 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003661 free(curproxy->expect_str);
3662 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3663 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003664 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3665 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3666 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3667 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
3670 }
3671 }
3672 else if (strcmp(ptr_arg, "rstring") == 0) {
3673 if (!*(args[cur_arg + 1])) {
3674 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3675 file, linenum, args[0], args[1], ptr_arg);
3676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
3678 }
3679 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003680 free(curproxy->expect_str);
3681 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3682 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003683 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3684 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3685 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3686 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690 }
3691 else {
3692 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3693 file, linenum, args[0], args[1], ptr_arg);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
3697 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003698 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003699 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 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003702 }
3703 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003704 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003705 if (curproxy == &defproxy) {
3706 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003709 }
3710
Willy Tarreaub80c2302007-11-30 20:51:32 +01003711 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003713
3714 if (strcmp(args[1], "fail") == 0) {
3715 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003716 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003717 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3718 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003721 }
3722
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003723 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3724 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3725 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003728 }
3729 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3730 }
3731 else {
3732 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003735 }
3736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737#ifdef TPROXY
3738 else if (!strcmp(args[0], "transparent")) {
3739 /* enable transparent proxy connections */
3740 curproxy->options |= PR_O_TRANSP;
3741 }
3742#endif
3743 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003744 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003746
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 if (*(args[1]) == 0) {
3748 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
3752 curproxy->maxconn = atol(args[1]);
3753 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003754 else if (!strcmp(args[0], "backlog")) { /* backlog */
3755 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003757
3758 if (*(args[1]) == 0) {
3759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003762 }
3763 curproxy->backlog = atol(args[1]);
3764 }
Willy Tarreau86034312006-12-29 00:10:33 +01003765 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003768
Willy Tarreau86034312006-12-29 00:10:33 +01003769 if (*(args[1]) == 0) {
3770 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003773 }
3774 curproxy->fullconn = atol(args[1]);
3775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3777 if (*(args[1]) == 0) {
3778 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003782 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3783 if (err) {
3784 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3785 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003788 }
3789 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
3791 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003792 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 if (curproxy == &defproxy) {
3794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003797 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003800
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 if (strchr(args[1], ':') == NULL) {
3802 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003806 sk = str2sa(args[1]);
3807 if (!sk) {
3808 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
3811 }
3812 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003813 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
3815 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003816 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003818
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003819 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3820 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003825 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3826 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3827 err_code |= ERR_WARN;
3828
3829 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3830 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3831 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3832 }
3833 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3834 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3835 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3836 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003837 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3838 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3839 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3840 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003841 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003842 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003847 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003849 char *rport, *raddr;
3850 short realport = 0;
3851 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003853 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003858 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860
3861 if (!*args[2]) {
3862 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3863 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003867
3868 err = invalid_char(args[1]);
3869 if (err) {
3870 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3871 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003874 }
3875
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003876 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003877 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003878
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003879 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3880 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3881 err_code |= ERR_ALERT | ERR_ABORT;
3882 goto out;
3883 }
3884
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003885 /* the servers are linked backwards first */
3886 newsrv->next = curproxy->srv;
3887 curproxy->srv = newsrv;
3888 newsrv->proxy = curproxy;
3889 newsrv->conf.file = file;
3890 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891
Simon Hormanaf514952011-06-21 14:34:57 +09003892 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003893 LIST_INIT(&newsrv->pendconns);
3894 do_check = 0;
3895 newsrv->state = SRV_RUNNING; /* early server setup */
3896 newsrv->last_change = now.tv_sec;
3897 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003899 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003900 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003901 * - IP: => port=+0, relative
3902 * - IP:N => port=N, absolute
3903 * - IP:+N => port=+N, relative
3904 * - IP:-N => port=-N, relative
3905 */
3906 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003907 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003908 if (rport) {
3909 *rport++ = 0;
3910 realport = atol(rport);
3911 if (!isdigit((unsigned char)*rport))
3912 newsrv->state |= SRV_MAPPORTS;
3913 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003915
Willy Tarreaufab5a432011-03-04 15:31:53 +01003916 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003917 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003918 if (!sk) {
3919 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
3922 }
3923 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003924 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02003925 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003926
3927 if (!sk) {
3928 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
3929 file, linenum, newsrv->addr.ss_family, args[2]);
3930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
3932 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003933 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003934
3935 newsrv->check_port = curproxy->defsrv.check_port;
3936 newsrv->inter = curproxy->defsrv.inter;
3937 newsrv->fastinter = curproxy->defsrv.fastinter;
3938 newsrv->downinter = curproxy->defsrv.downinter;
3939 newsrv->rise = curproxy->defsrv.rise;
3940 newsrv->fall = curproxy->defsrv.fall;
3941 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3942 newsrv->minconn = curproxy->defsrv.minconn;
3943 newsrv->maxconn = curproxy->defsrv.maxconn;
3944 newsrv->slowstart = curproxy->defsrv.slowstart;
3945 newsrv->onerror = curproxy->defsrv.onerror;
3946 newsrv->consecutive_errors_limit
3947 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02003948#ifdef OPENSSL
3949 newsrv->use_ssl = curproxy->defsrv.use_ssl;
3950#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003951 newsrv->uweight = newsrv->iweight
3952 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003954 newsrv->curfd = -1; /* no health-check in progress */
3955 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003957 cur_arg = 3;
3958 } else {
3959 newsrv = &curproxy->defsrv;
3960 cur_arg = 1;
3961 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003962
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003964 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003965 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003966
3967 if (!*args[cur_arg + 1]) {
3968 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3969 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003972 }
3973
3974 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003975 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003976
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003977 if (newsrv->puid <= 0) {
3978 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003979 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003982 }
3983
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003984 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3985 if (node) {
3986 struct server *target = container_of(node, struct server, conf.id);
3987 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3988 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
3991 }
3992 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003993 cur_arg += 2;
3994 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003995 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 newsrv->cookie = strdup(args[cur_arg + 1]);
3997 newsrv->cklen = strlen(args[cur_arg + 1]);
3998 cur_arg += 2;
3999 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004000 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004001 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4002 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4003 cur_arg += 2;
4004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004006 if (!*args[cur_arg + 1]) {
4007 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4008 file, linenum, args[cur_arg]);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
4012
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004014 if (newsrv->rise <= 0) {
4015 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4016 file, linenum, args[cur_arg]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
Willy Tarreau96839092010-03-29 10:02:24 +02004021 if (newsrv->health)
4022 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 cur_arg += 2;
4024 }
4025 else if (!strcmp(args[cur_arg], "fall")) {
4026 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004027
4028 if (!*args[cur_arg + 1]) {
4029 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4030 file, linenum, args[cur_arg]);
4031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
4033 }
4034
4035 if (newsrv->fall <= 0) {
4036 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4037 file, linenum, args[cur_arg]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 cur_arg += 2;
4043 }
4044 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004045 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4046 if (err) {
4047 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4048 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004049 err_code |= ERR_ALERT | ERR_FATAL;
4050 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004051 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004052 if (val <= 0) {
4053 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4054 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004057 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004058 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 cur_arg += 2;
4060 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004061 else if (!strcmp(args[cur_arg], "fastinter")) {
4062 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4063 if (err) {
4064 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4065 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004068 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004069 if (val <= 0) {
4070 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4071 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004074 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004075 newsrv->fastinter = val;
4076 cur_arg += 2;
4077 }
4078 else if (!strcmp(args[cur_arg], "downinter")) {
4079 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4080 if (err) {
4081 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4082 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004085 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004086 if (val <= 0) {
4087 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4088 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004091 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004092 newsrv->downinter = val;
4093 cur_arg += 2;
4094 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004095 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004096 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004097 if (!sk) {
4098 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
4102 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004103 cur_arg += 2;
4104 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004105 else if (!strcmp(args[cur_arg], "port")) {
4106 newsrv->check_port = atol(args[cur_arg + 1]);
4107 cur_arg += 2;
4108 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004109 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 newsrv->state |= SRV_BACKUP;
4111 cur_arg ++;
4112 }
Simon Hormanfa461682011-06-25 09:39:49 +09004113 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4114 newsrv->state |= SRV_NON_STICK;
4115 cur_arg ++;
4116 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004117 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4118 newsrv->state |= SRV_SEND_PROXY;
4119 cur_arg ++;
4120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 else if (!strcmp(args[cur_arg], "weight")) {
4122 int w;
4123 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004124 if (w < 0 || w > 256) {
4125 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004130 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 cur_arg += 2;
4132 }
4133 else if (!strcmp(args[cur_arg], "minconn")) {
4134 newsrv->minconn = atol(args[cur_arg + 1]);
4135 cur_arg += 2;
4136 }
4137 else if (!strcmp(args[cur_arg], "maxconn")) {
4138 newsrv->maxconn = atol(args[cur_arg + 1]);
4139 cur_arg += 2;
4140 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004141 else if (!strcmp(args[cur_arg], "maxqueue")) {
4142 newsrv->maxqueue = atol(args[cur_arg + 1]);
4143 cur_arg += 2;
4144 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004145 else if (!strcmp(args[cur_arg], "slowstart")) {
4146 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004147 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004148 if (err) {
4149 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4150 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004153 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004154 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004155 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4156 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004159 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004160 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004161 cur_arg += 2;
4162 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004163 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004164
4165 if (!*args[cur_arg + 1]) {
4166 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4167 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004170 }
4171
4172 newsrv->trackit = strdup(args[cur_arg + 1]);
4173
4174 cur_arg += 2;
4175 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004176 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 global.maxsock++;
4178 do_check = 1;
4179 cur_arg += 1;
4180 }
Willy Tarreau96839092010-03-29 10:02:24 +02004181 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4182 newsrv->state |= SRV_MAINTAIN;
4183 newsrv->state &= ~SRV_RUNNING;
4184 newsrv->health = 0;
4185 cur_arg += 1;
4186 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004187 else if (!strcmp(args[cur_arg], "ssl")) {
4188#ifdef USE_OPENSSL
4189 newsrv->use_ssl = 1;
4190 cur_arg += 1;
4191#else /* USE_OPENSSL */
4192 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4193 file, linenum, args[cur_arg]);
4194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
4196#endif /* USE_OPENSSL */
4197 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004198 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4199#ifdef USE_OPENSSL
4200 if (!*args[cur_arg + 1]) {
4201 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4202 file, linenum, args[0], args[cur_arg]);
4203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
4205 }
4206
4207 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4208
4209 cur_arg += 2;
4210 continue;
4211#else
4212 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4213 file, linenum, args[0], args[cur_arg]);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216#endif
4217 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004218 else if (!strcmp(args[cur_arg], "nosslv3")) {
4219#ifdef USE_OPENSSL
4220 newsrv->ssl_ctx.nosslv3 = 1;
4221 cur_arg += 1;
4222#else /* USE_OPENSSL */
4223 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4224 file, linenum, args[cur_arg]);
4225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
4227#endif /* USE_OPENSSL */
4228 }
4229 else if (!strcmp(args[cur_arg], "notlsv1")) {
4230#ifdef USE_OPENSSL
4231 newsrv->ssl_ctx.notlsv1 = 1;
4232 cur_arg += 1;
4233#else /* USE_OPENSSL */
4234 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4235 file, linenum, args[cur_arg]);
4236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
4238#endif /* USE_OPENSSL */
4239 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004240 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004241 if (!strcmp(args[cur_arg + 1], "none"))
4242 newsrv->observe = HANA_OBS_NONE;
4243 else if (!strcmp(args[cur_arg + 1], "layer4"))
4244 newsrv->observe = HANA_OBS_LAYER4;
4245 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4246 if (curproxy->mode != PR_MODE_HTTP) {
4247 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4248 file, linenum, args[cur_arg + 1]);
4249 err_code |= ERR_ALERT;
4250 }
4251 newsrv->observe = HANA_OBS_LAYER7;
4252 }
4253 else {
4254 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004255 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004256 file, linenum, args[cur_arg], args[cur_arg + 1]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
4261 cur_arg += 2;
4262 }
4263 else if (!strcmp(args[cur_arg], "on-error")) {
4264 if (!strcmp(args[cur_arg + 1], "fastinter"))
4265 newsrv->onerror = HANA_ONERR_FASTINTER;
4266 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4267 newsrv->onerror = HANA_ONERR_FAILCHK;
4268 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4269 newsrv->onerror = HANA_ONERR_SUDDTH;
4270 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4271 newsrv->onerror = HANA_ONERR_MARKDWN;
4272 else {
4273 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004274 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004275 file, linenum, args[cur_arg], args[cur_arg + 1]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
4280 cur_arg += 2;
4281 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004282 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4283 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4284 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4285 else {
4286 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4287 file, linenum, args[cur_arg], args[cur_arg + 1]);
4288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
4291
4292 cur_arg += 2;
4293 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004294 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4295 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4296 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4297 else {
4298 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4299 file, linenum, args[cur_arg], args[cur_arg + 1]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
4302 }
4303
4304 cur_arg += 2;
4305 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004306 else if (!strcmp(args[cur_arg], "error-limit")) {
4307 if (!*args[cur_arg + 1]) {
4308 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4309 file, linenum, args[cur_arg]);
4310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313
4314 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4315
4316 if (newsrv->consecutive_errors_limit <= 0) {
4317 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4318 file, linenum, args[cur_arg]);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004322 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004323 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004324 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004325 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004326 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004327
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004329#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004330 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004331 file, linenum, "source", "usesrc");
4332#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004333 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004335#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 }
4339 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004340 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4341 if (!sk) {
4342 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004347
4348 if (port_low != port_high) {
4349 int i;
4350 if (port_low <= 0 || port_low > 65535 ||
4351 port_high <= 0 || port_high > 65535 ||
4352 port_low > port_high) {
4353 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4354 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004357 }
4358 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4359 for (i = 0; i < newsrv->sport_range->size; i++)
4360 newsrv->sport_range->ports[i] = port_low + i;
4361 }
4362
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004364 while (*(args[cur_arg])) {
4365 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004366#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4367#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004368 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4369 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4370 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004373 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004374#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004375 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004376 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004377 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004380 }
4381 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004382 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 newsrv->state |= SRV_TPROXY_CLI;
4384 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004385 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004387 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4388 char *name, *end;
4389
4390 name = args[cur_arg+1] + 7;
4391 while (isspace(*name))
4392 name++;
4393
4394 end = name;
4395 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4396 end++;
4397
4398 newsrv->state &= ~SRV_TPROXY_MASK;
4399 newsrv->state |= SRV_TPROXY_DYN;
4400 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4401 newsrv->bind_hdr_len = end - name;
4402 memcpy(newsrv->bind_hdr_name, name, end - name);
4403 newsrv->bind_hdr_name[end-name] = '\0';
4404 newsrv->bind_hdr_occ = -1;
4405
4406 /* now look for an occurrence number */
4407 while (isspace(*end))
4408 end++;
4409 if (*end == ',') {
4410 end++;
4411 name = end;
4412 if (*end == '-')
4413 end++;
4414 while (isdigit(*end))
4415 end++;
4416 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4417 }
4418
4419 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4420 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4421 " occurrences values smaller than %d.\n",
4422 file, linenum, MAX_HDR_HISTORY);
4423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
4425 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004427 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004428 if (!sk) {
4429 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
4433 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004434 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 }
4436 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004437#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004438 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004439#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004440 cur_arg += 2;
4441 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004442#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004443 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004444 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004447#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4448 } /* "usesrc" */
4449
4450 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4451#ifdef SO_BINDTODEVICE
4452 if (!*args[cur_arg + 1]) {
4453 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4454 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004457 }
4458 if (newsrv->iface_name)
4459 free(newsrv->iface_name);
4460
4461 newsrv->iface_name = strdup(args[cur_arg + 1]);
4462 newsrv->iface_len = strlen(newsrv->iface_name);
4463 global.last_checks |= LSTCHK_NETADM;
4464#else
4465 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4466 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004469#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004470 cur_arg += 2;
4471 continue;
4472 }
4473 /* this keyword in not an option of "source" */
4474 break;
4475 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004477 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004478 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4479 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004484 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004485 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 +01004486 file, linenum, newsrv->id);
4487 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004488 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 +01004489 file, linenum);
4490
Willy Tarreau93893792009-07-23 13:19:11 +02004491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 }
4494 }
4495
4496 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004497 if (newsrv->trackit) {
4498 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4499 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004502 }
4503
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004504 /* try to get the port from check_addr if check_port not set */
4505 if (!newsrv->check_port)
4506 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004507
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4509 newsrv->check_port = realport; /* by default */
4510 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004511 /* not yet valid, because no port was set on
4512 * the server either. We'll check if we have
4513 * a known port on the first listener.
4514 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004515 struct listener *l = curproxy->listen;
4516 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4517 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004518 }
4519 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4521 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004522 err_code |= ERR_ALERT | ERR_FATAL;
4523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004525
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004526 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004527 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004528 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4529 err_code |= ERR_ALERT | ERR_ABORT;
4530 goto out;
4531 }
4532
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004533 /* Allocate buffer for partial check results... */
4534 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4535 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4536 err_code |= ERR_ALERT | ERR_ABORT;
4537 goto out;
4538 }
4539
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004540 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 newsrv->state |= SRV_CHECKED;
4542 }
4543
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004544 if (!defsrv) {
4545 if (newsrv->state & SRV_BACKUP)
4546 curproxy->srv_bck++;
4547 else
4548 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004549
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004550 newsrv->prev_state = newsrv->state;
4551 }
William Lallemanda73203e2012-03-12 12:48:57 +01004552 }
4553
4554 else if (strcmp(args[0], "unique-id-format") == 0) {
4555 if (!*(args[1])) {
4556 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
4559 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004560 free(curproxy->uniqueid_format_string);
4561 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004562 }
William Lallemanda73203e2012-03-12 12:48:57 +01004563
4564 else if (strcmp(args[0], "unique-id-header") == 0) {
4565 if (!*(args[1])) {
4566 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
4569 }
4570 free(curproxy->header_unique_id);
4571 curproxy->header_unique_id = strdup(args[1]);
4572 }
4573
William Lallemand723b73a2012-02-08 16:37:49 +01004574 else if (strcmp(args[0], "log-format") == 0) {
4575 if (!*(args[1])) {
4576 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
4579 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004580
4581 if (curproxy->logformat_string != default_http_log_format &&
4582 curproxy->logformat_string != default_tcp_log_format &&
4583 curproxy->logformat_string != clf_http_log_format)
4584 free(curproxy->logformat_string);
4585 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 }
William Lallemand723b73a2012-02-08 16:37:49 +01004587
William Lallemand0f99e342011-10-12 17:50:54 +02004588 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4589 /* delete previous herited or defined syslog servers */
4590 struct logsrv *back;
4591
4592 if (*(args[1]) != 0) {
4593 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
4596 }
4597
William Lallemand723b73a2012-02-08 16:37:49 +01004598 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4599 LIST_DEL(&tmplogsrv->list);
4600 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004601 }
4602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004604 struct logsrv *logsrv;
4605
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004607 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004608 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004609 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004610 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004611 LIST_INIT(&node->list);
4612 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614 }
4615 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004616
4617 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618
William Lallemand0f99e342011-10-12 17:50:54 +02004619 logsrv->facility = get_log_facility(args[2]);
4620 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625 }
4626
William Lallemand0f99e342011-10-12 17:50:54 +02004627 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004629 logsrv->level = get_log_level(args[3]);
4630 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 }
4636 }
4637
William Lallemand0f99e342011-10-12 17:50:54 +02004638 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004639 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004640 logsrv->minlvl = get_log_level(args[4]);
4641 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004642 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
4645
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004646 }
4647 }
4648
Robert Tsai81ae1952007-12-05 10:47:29 +01004649 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004650 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004651 if (!sk) {
4652 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004653 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
4656 }
William Lallemand0f99e342011-10-12 17:50:54 +02004657 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004658 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004659 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004660 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004661 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4662 err_code |= ERR_ALERT | ERR_FATAL;
4663 goto out;
4664 }
William Lallemand0f99e342011-10-12 17:50:54 +02004665 logsrv->addr = *sk;
4666 if (!get_host_port(&logsrv->addr))
4667 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 }
William Lallemand0f99e342011-10-12 17:50:54 +02004669
4670 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004671 }
4672 else {
4673 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4674 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 }
4678 }
4679 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004680 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004681 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004682
Willy Tarreau977b8e42006-12-29 14:19:17 +01004683 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004684 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004685
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004687 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4688 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004692
4693 /* we must first clear any optional default setting */
4694 curproxy->options &= ~PR_O_TPXY_MASK;
4695 free(curproxy->iface_name);
4696 curproxy->iface_name = NULL;
4697 curproxy->iface_len = 0;
4698
Willy Tarreaud5191e72010-02-09 20:50:45 +01004699 sk = str2sa(args[1]);
4700 if (!sk) {
4701 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4702 err_code |= ERR_ALERT | ERR_FATAL;
4703 goto out;
4704 }
4705 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004706 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004707
4708 cur_arg = 2;
4709 while (*(args[cur_arg])) {
4710 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004711#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4712#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004713 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4714 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4715 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004718 }
4719#endif
4720 if (!*args[cur_arg + 1]) {
4721 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4722 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004725 }
4726
4727 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004728 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004729 curproxy->options |= PR_O_TPXY_CLI;
4730 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004731 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004732 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004733 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4734 char *name, *end;
4735
4736 name = args[cur_arg+1] + 7;
4737 while (isspace(*name))
4738 name++;
4739
4740 end = name;
4741 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4742 end++;
4743
4744 curproxy->options &= ~PR_O_TPXY_MASK;
4745 curproxy->options |= PR_O_TPXY_DYN;
4746 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4747 curproxy->bind_hdr_len = end - name;
4748 memcpy(curproxy->bind_hdr_name, name, end - name);
4749 curproxy->bind_hdr_name[end-name] = '\0';
4750 curproxy->bind_hdr_occ = -1;
4751
4752 /* now look for an occurrence number */
4753 while (isspace(*end))
4754 end++;
4755 if (*end == ',') {
4756 end++;
4757 name = end;
4758 if (*end == '-')
4759 end++;
4760 while (isdigit(*end))
4761 end++;
4762 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4763 }
4764
4765 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4766 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4767 " occurrences values smaller than %d.\n",
4768 file, linenum, MAX_HDR_HISTORY);
4769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
4771 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004772 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004773 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004774 if (!sk) {
4775 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
4778 }
4779 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004780 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004781 }
4782 global.last_checks |= LSTCHK_NETADM;
4783#if !defined(CONFIG_HAP_LINUX_TPROXY)
4784 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004785#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004786#else /* no TPROXY support */
4787 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004788 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004791#endif
4792 cur_arg += 2;
4793 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004794 }
4795
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004796 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4797#ifdef SO_BINDTODEVICE
4798 if (!*args[cur_arg + 1]) {
4799 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4800 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004803 }
4804 if (curproxy->iface_name)
4805 free(curproxy->iface_name);
4806
4807 curproxy->iface_name = strdup(args[cur_arg + 1]);
4808 curproxy->iface_len = strlen(curproxy->iface_name);
4809 global.last_checks |= LSTCHK_NETADM;
4810#else
4811 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4812 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004815#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004816 cur_arg += 2;
4817 continue;
4818 }
4819 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4820 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004825 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4826 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4827 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004828 err_code |= ERR_ALERT | ERR_FATAL;
4829 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4834 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004838
4839 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004840 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004841 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004844 }
4845 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004846 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004847 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004848 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 }
4852 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004853 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004854 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004855 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004856 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 }
4859 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004860 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004861 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004862 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004863 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 }
4866 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004867 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004868 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004869 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004870 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004873 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004874 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004875 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004876 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004877 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004878 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004879 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004880 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004881 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004882 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004883 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004884 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004885 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004886 }
4887 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004888 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004889 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004890 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004891 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004892 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004895 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4897 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901
4902 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004903 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004904 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
4908 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004910 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004911 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
4915 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004917 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004918 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
4922 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004924 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004925 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
4929 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004931 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004932 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004936 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004938 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004939 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004941 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004944 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004945
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 if (curproxy == &defproxy) {
4947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004951 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004952 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 if (*(args[1]) == 0) {
4955 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004959
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004960 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004961 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
4962 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
4963 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
4966 }
4967 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4968 }
4969 else if (*args[2]) {
4970 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4971 file, linenum, args[0], args[2]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004976 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004977 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004978 wl->s = strdup(args[1]);
4979 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004980 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
4982 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4985 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004989
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004991 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004992 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
4996 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004998 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004999 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
5003 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005004 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005005 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005006 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005007 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 }
5010 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005011 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 }
5017
Willy Tarreauade5ec42010-01-28 19:33:49 +01005018 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005019 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005020 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005021 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
5024 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005026 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005027 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005028 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
5031 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005033 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005034 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005035 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
5038 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005039 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005040
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 if (curproxy == &defproxy) {
5042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005046 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 if (*(args[1]) == 0) {
5050 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
5054
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005055 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005056 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5057 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5058 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
5061 }
5062 err_code |= warnif_cond_requires_req(cond, file, linenum);
5063 }
5064 else if (*args[2]) {
5065 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5066 file, linenum, args[0], args[2]);
5067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
5069 }
5070
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005071 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005072 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005073 wl->s = strdup(args[1]);
5074 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
5076 else if (!strcmp(args[0], "errorloc") ||
5077 !strcmp(args[0], "errorloc302") ||
5078 !strcmp(args[0], "errorloc303")) { /* error location */
5079 int errnum, errlen;
5080 char *err;
5081
Willy Tarreau977b8e42006-12-29 14:19:17 +01005082 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005084
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005086 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
5090
5091 errnum = atol(args[1]);
5092 if (!strcmp(args[0], "errorloc303")) {
5093 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5094 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5095 } else {
5096 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5097 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5098 }
5099
Willy Tarreau0f772532006-12-23 20:51:41 +01005100 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5101 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005102 chunk_destroy(&curproxy->errmsg[rc]);
5103 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005104 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005107
5108 if (rc >= HTTP_ERR_SIZE) {
5109 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5110 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 free(err);
5112 }
5113 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005114 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5115 int errnum, errlen, fd;
5116 char *err;
5117 struct stat stat;
5118
5119 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005121
5122 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005123 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005126 }
5127
5128 fd = open(args[2], O_RDONLY);
5129 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5130 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5131 file, linenum, args[2], args[1]);
5132 if (fd >= 0)
5133 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005136 }
5137
Willy Tarreau27a674e2009-08-17 07:23:33 +02005138 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005139 errlen = stat.st_size;
5140 } else {
5141 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005142 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005144 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005145 }
5146
5147 err = malloc(errlen); /* malloc() must succeed during parsing */
5148 errnum = read(fd, err, errlen);
5149 if (errnum != errlen) {
5150 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5151 file, linenum, args[2], args[1]);
5152 close(fd);
5153 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005156 }
5157 close(fd);
5158
5159 errnum = atol(args[1]);
5160 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5161 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005162 chunk_destroy(&curproxy->errmsg[rc]);
5163 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005164 break;
5165 }
5166 }
5167
5168 if (rc >= HTTP_ERR_SIZE) {
5169 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5170 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005171 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005172 free(err);
5173 }
5174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005176 struct cfg_kw_list *kwl;
5177 int index;
5178
5179 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5180 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5181 if (kwl->kw[index].section != CFG_LISTEN)
5182 continue;
5183 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5184 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005185 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005186 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005187 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005188 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005189 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005192 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005193 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005194 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_WARN;
5196 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005197 }
Willy Tarreau93893792009-07-23 13:19:11 +02005198 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005199 }
5200 }
5201 }
5202
Willy Tarreau6daf3432008-01-22 16:44:08 +01005203 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 }
Willy Tarreau93893792009-07-23 13:19:11 +02005207 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005208 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005209 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210}
5211
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005212int
5213cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5214{
5215
5216 int err_code = 0;
5217 const char *err;
5218
5219 if (!strcmp(args[0], "userlist")) { /* new userlist */
5220 struct userlist *newul;
5221
5222 if (!*args[1]) {
5223 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5224 file, linenum, args[0]);
5225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
5227 }
5228
5229 err = invalid_char(args[1]);
5230 if (err) {
5231 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5232 file, linenum, *err, args[0], args[1]);
5233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
5235 }
5236
5237 for (newul = userlist; newul; newul = newul->next)
5238 if (!strcmp(newul->name, args[1])) {
5239 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5240 file, linenum, args[1]);
5241 err_code |= ERR_WARN;
5242 goto out;
5243 }
5244
5245 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5246 if (!newul) {
5247 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5248 err_code |= ERR_ALERT | ERR_ABORT;
5249 goto out;
5250 }
5251
5252 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5253 newul->name = strdup(args[1]);
5254
5255 if (!newul->groupusers | !newul->name) {
5256 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5257 err_code |= ERR_ALERT | ERR_ABORT;
5258 goto out;
5259 }
5260
5261 newul->next = userlist;
5262 userlist = newul;
5263
5264 } else if (!strcmp(args[0], "group")) { /* new group */
5265 int cur_arg, i;
5266 const char *err;
5267
5268 if (!*args[1]) {
5269 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5270 file, linenum, args[0]);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274
5275 err = invalid_char(args[1]);
5276 if (err) {
5277 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5278 file, linenum, *err, args[0], args[1]);
5279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
5281 }
5282
5283 for(i = 0; i < userlist->grpcnt; i++)
5284 if (!strcmp(userlist->groups[i], args[1])) {
5285 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5286 file, linenum, args[1], userlist->name);
5287 err_code |= ERR_ALERT;
5288 goto out;
5289 }
5290
5291 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5292 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5293 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
5296 }
5297
5298 cur_arg = 2;
5299
5300 while (*args[cur_arg]) {
5301 if (!strcmp(args[cur_arg], "users")) {
5302 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5303 cur_arg += 2;
5304 continue;
5305 } else {
5306 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5307 file, linenum, args[0]);
5308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
5310 }
5311 }
5312
5313 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5314 } else if (!strcmp(args[0], "user")) { /* new user */
5315 struct auth_users *newuser;
5316 int cur_arg;
5317
5318 if (!*args[1]) {
5319 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5320 file, linenum, args[0]);
5321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
5323 }
5324
5325 for (newuser = userlist->users; newuser; newuser = newuser->next)
5326 if (!strcmp(newuser->user, args[1])) {
5327 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5328 file, linenum, args[1], userlist->name);
5329 err_code |= ERR_ALERT;
5330 goto out;
5331 }
5332
5333 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5334 if (!newuser) {
5335 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5336 err_code |= ERR_ALERT | ERR_ABORT;
5337 goto out;
5338 }
5339
5340 newuser->user = strdup(args[1]);
5341
5342 newuser->next = userlist->users;
5343 userlist->users = newuser;
5344
5345 cur_arg = 2;
5346
5347 while (*args[cur_arg]) {
5348 if (!strcmp(args[cur_arg], "password")) {
5349#ifndef CONFIG_HAP_CRYPT
5350 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5351 file, linenum);
5352 err_code |= ERR_ALERT;
5353#endif
5354 newuser->pass = strdup(args[cur_arg + 1]);
5355 cur_arg += 2;
5356 continue;
5357 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5358 newuser->pass = strdup(args[cur_arg + 1]);
5359 newuser->flags |= AU_O_INSECURE;
5360 cur_arg += 2;
5361 continue;
5362 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005363 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005364 cur_arg += 2;
5365 continue;
5366 } else {
5367 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5368 file, linenum, args[0]);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372 }
5373 } else {
5374 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5375 err_code |= ERR_ALERT | ERR_FATAL;
5376 }
5377
5378out:
5379 return err_code;
5380}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381
5382/*
5383 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005384 * Returns the error code, 0 if OK, or any combination of :
5385 * - ERR_ABORT: must abort ASAP
5386 * - ERR_FATAL: we can continue parsing but not start the service
5387 * - ERR_WARN: a warning has been emitted
5388 * - ERR_ALERT: an alert has been emitted
5389 * Only the two first ones can stop processing, the two others are just
5390 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005392int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005394 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005395 FILE *f;
5396 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005398 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 if ((f=fopen(file,"r")) == NULL)
5401 return -1;
5402
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005403 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005404 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005405 char *end;
5406 char *args[MAX_LINE_ARGS + 1];
5407 char *line = thisline;
5408
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409 linenum++;
5410
5411 end = line + strlen(line);
5412
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005413 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5414 /* Check if we reached the limit and the last char is not \n.
5415 * Watch out for the last line without the terminating '\n'!
5416 */
5417 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005418 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005419 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005420 }
5421
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005423 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 line++;
5425
5426 arg = 0;
5427 args[arg] = line;
5428
5429 while (*line && arg < MAX_LINE_ARGS) {
5430 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5431 * C equivalent value. Other combinations left unchanged (eg: \1).
5432 */
5433 if (*line == '\\') {
5434 int skip = 0;
5435 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5436 *line = line[1];
5437 skip = 1;
5438 }
5439 else if (line[1] == 'r') {
5440 *line = '\r';
5441 skip = 1;
5442 }
5443 else if (line[1] == 'n') {
5444 *line = '\n';
5445 skip = 1;
5446 }
5447 else if (line[1] == 't') {
5448 *line = '\t';
5449 skip = 1;
5450 }
5451 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005452 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 unsigned char hex1, hex2;
5454 hex1 = toupper(line[2]) - '0';
5455 hex2 = toupper(line[3]) - '0';
5456 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5457 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5458 *line = (hex1<<4) + hex2;
5459 skip = 3;
5460 }
5461 else {
5462 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 }
5465 }
5466 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005467 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 end -= skip;
5469 }
5470 line++;
5471 }
5472 else if (*line == '#' || *line == '\n' || *line == '\r') {
5473 /* end of string, end of loop */
5474 *line = 0;
5475 break;
5476 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005477 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005479 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005480 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 line++;
5482 args[++arg] = line;
5483 }
5484 else {
5485 line++;
5486 }
5487 }
5488
5489 /* empty line */
5490 if (!**args)
5491 continue;
5492
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005493 if (*line) {
5494 /* we had to stop due to too many args.
5495 * Let's terminate the string, print the offending part then cut the
5496 * last arg.
5497 */
5498 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5499 line++;
5500 *line = '\0';
5501
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005502 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005503 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005504 err_code |= ERR_ALERT | ERR_FATAL;
5505 args[arg] = line;
5506 }
5507
Willy Tarreau540abe42007-05-02 20:50:16 +02005508 /* zero out remaining args and ensure that at least one entry
5509 * is zeroed out.
5510 */
5511 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 args[arg] = line;
5513 }
5514
Willy Tarreau3842f002009-06-14 11:39:52 +02005515 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005516 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005517 char *tmp;
5518
Willy Tarreau3842f002009-06-14 11:39:52 +02005519 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005520 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005521 for (arg=0; *args[arg+1]; arg++)
5522 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005523 *tmp = '\0'; // fix the next arg to \0
5524 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005525 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005526 else if (!strcmp(args[0], "default")) {
5527 kwm = KWM_DEF;
5528 for (arg=0; *args[arg+1]; arg++)
5529 args[arg] = args[arg+1]; // shift args after inversion
5530 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005531
William Lallemand0f99e342011-10-12 17:50:54 +02005532 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5533 strcmp(args[0], "log") != 0) {
5534 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005536 }
5537
Willy Tarreau977b8e42006-12-29 14:19:17 +01005538 if (!strcmp(args[0], "listen") ||
5539 !strcmp(args[0], "frontend") ||
5540 !strcmp(args[0], "backend") ||
5541 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005542 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005544 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005545 cursection = strdup(args[0]);
5546 }
5547 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005549 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005550 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005551 }
5552 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005553 confsect = CFG_USERLIST;
5554 free(cursection);
5555 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005556 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005557 else if (!strcmp(args[0], "peers")) {
5558 confsect = CFG_PEERS;
5559 free(cursection);
5560 cursection = strdup(args[0]);
5561 }
5562
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 /* else it's a section keyword */
5564
5565 switch (confsect) {
5566 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 break;
5569 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005570 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005571 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005572 case CFG_USERLIST:
5573 err_code |= cfg_parse_users(file, linenum, args, kwm);
5574 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005575 case CFG_PEERS:
5576 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5577 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005579 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005580 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005582
5583 if (err_code & ERR_ABORT)
5584 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005586 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005587 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005589 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005590}
5591
Willy Tarreaubb925012009-07-23 13:36:36 +02005592/*
5593 * Returns the error code, 0 if OK, or any combination of :
5594 * - ERR_ABORT: must abort ASAP
5595 * - ERR_FATAL: we can continue parsing but not start the service
5596 * - ERR_WARN: a warning has been emitted
5597 * - ERR_ALERT: an alert has been emitted
5598 * Only the two first ones can stop processing, the two others are just
5599 * indicators.
5600 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005601int check_config_validity()
5602{
5603 int cfgerr = 0;
5604 struct proxy *curproxy = NULL;
5605 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005606 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005607 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005608 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005609 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005611 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 /*
5613 * Now, check for the integrity of all that we have collected.
5614 */
5615
5616 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005617 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005618
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005619 /* first, we will invert the proxy list order */
5620 curproxy = NULL;
5621 while (proxy) {
5622 struct proxy *next;
5623
5624 next = proxy->next;
5625 proxy->next = curproxy;
5626 curproxy = proxy;
5627 if (!next)
5628 break;
5629 proxy = next;
5630 }
5631
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005633 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005634 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005635 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005636 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005637 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005638 unsigned int next_id;
5639
5640 if (!curproxy->uuid) {
5641 /* proxy ID not set, use automatic numbering with first
5642 * spare entry starting with next_pxid.
5643 */
5644 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5645 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5646 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005647 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005648 next_pxid++;
5649
Willy Tarreau55ea7572007-06-17 19:56:27 +02005650
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005652 /* ensure we don't keep listeners uselessly bound */
5653 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005654 curproxy = curproxy->next;
5655 continue;
5656 }
5657
Willy Tarreauff01a212009-03-15 13:46:16 +01005658 switch (curproxy->mode) {
5659 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005660 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005661 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005662 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5663 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005664 cfgerr++;
5665 }
5666
5667 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005668 Warning("config : servers will be ignored for %s '%s'.\n",
5669 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005670 break;
5671
5672 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005673 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005674 break;
5675
5676 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005677 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005678 break;
5679 }
5680
5681 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005682 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5683 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 cfgerr++;
5685 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005686
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005687 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005688 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005689 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005690 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5691 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005692 cfgerr++;
5693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005695 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005696 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5697 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005698 cfgerr++;
5699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005701 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005702 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5703 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005704 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005705 }
5706 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005707 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005708 /* If no LB algo is set in a backend, and we're not in
5709 * transparent mode, dispatch mode nor proxy mode, we
5710 * want to use balance roundrobin by default.
5711 */
5712 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5713 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 }
5715 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005716
Willy Tarreau1620ec32011-08-06 17:05:02 +02005717 if (curproxy->options & PR_O_DISPATCH)
5718 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5719 else if (curproxy->options & PR_O_HTTP_PROXY)
5720 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5721 else if (curproxy->options & PR_O_TRANSP)
5722 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005723
Willy Tarreau1620ec32011-08-06 17:05:02 +02005724 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5725 if (curproxy->options & PR_O_DISABLE404) {
5726 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5727 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5728 err_code |= ERR_WARN;
5729 curproxy->options &= ~PR_O_DISABLE404;
5730 }
5731 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5732 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5733 "send-state", proxy_type_str(curproxy), curproxy->id);
5734 err_code |= ERR_WARN;
5735 curproxy->options &= ~PR_O2_CHK_SNDST;
5736 }
Willy Tarreauef781042010-01-27 11:53:01 +01005737 }
5738
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005739 /* if a default backend was specified, let's find it */
5740 if (curproxy->defbe.name) {
5741 struct proxy *target;
5742
Alex Williams96532db2009-11-01 21:27:13 -05005743 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005744 if (!target) {
5745 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5746 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005747 cfgerr++;
5748 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005749 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5750 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005751 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005752 } else {
5753 free(curproxy->defbe.name);
5754 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005755 /* we force the backend to be present on at least all of
5756 * the frontend's processes.
5757 */
5758 target->bind_proc = curproxy->bind_proc ?
5759 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005760
5761 /* Emit a warning if this proxy also has some servers */
5762 if (curproxy->srv) {
5763 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5764 curproxy->id);
5765 err_code |= ERR_WARN;
5766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 }
5768 }
5769
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005770 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005771 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5772 /* map jump target for ACT_SETBE in req_rep chain */
5773 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005774 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005775 struct proxy *target;
5776
Willy Tarreaua496b602006-12-17 23:15:24 +01005777 if (exp->action != ACT_SETBE)
5778 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005779
Alex Williams96532db2009-11-01 21:27:13 -05005780 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005781 if (!target) {
5782 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5783 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005784 cfgerr++;
5785 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005786 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5787 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005788 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005789 } else {
5790 free((void *)exp->replace);
5791 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005792 /* we force the backend to be present on at least all of
5793 * the frontend's processes.
5794 */
5795 target->bind_proc = curproxy->bind_proc ?
5796 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005797 }
5798 }
5799 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005800
5801 /* find the target proxy for 'use_backend' rules */
5802 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005803 struct proxy *target;
5804
Alex Williams96532db2009-11-01 21:27:13 -05005805 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005806
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005807 if (!target) {
5808 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5809 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005810 cfgerr++;
5811 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005812 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5813 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005814 cfgerr++;
5815 } else {
5816 free((void *)rule->be.name);
5817 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005818 /* we force the backend to be present on at least all of
5819 * the frontend's processes.
5820 */
5821 target->bind_proc = curproxy->bind_proc ?
5822 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005823 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005824 }
5825
5826 /* find the target proxy for 'use_backend' rules */
5827 list_for_each_entry(srule, &curproxy->server_rules, list) {
5828 struct server *target = findserver(curproxy, srule->srv.name);
5829
5830 if (!target) {
5831 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5832 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5833 cfgerr++;
5834 continue;
5835 }
5836 free((void *)srule->srv.name);
5837 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005838 }
5839
Emeric Brunb982a3d2010-01-04 15:45:53 +01005840 /* find the target table for 'stick' rules */
5841 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5842 struct proxy *target;
5843
Emeric Brun1d33b292010-01-04 15:47:17 +01005844 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5845 if (mrule->flags & STK_IS_STORE)
5846 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5847
Emeric Brunb982a3d2010-01-04 15:45:53 +01005848 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005849 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005850 else
5851 target = curproxy;
5852
5853 if (!target) {
5854 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5855 curproxy->id, mrule->table.name);
5856 cfgerr++;
5857 }
5858 else if (target->table.size == 0) {
5859 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5860 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5861 cfgerr++;
5862 }
Willy Tarreau12785782012-04-27 21:37:17 +02005863 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5864 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005865 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5866 cfgerr++;
5867 }
5868 else {
5869 free((void *)mrule->table.name);
5870 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005871 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005872 }
5873 }
5874
5875 /* find the target table for 'store response' rules */
5876 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5877 struct proxy *target;
5878
Emeric Brun1d33b292010-01-04 15:47:17 +01005879 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5880
Emeric Brunb982a3d2010-01-04 15:45:53 +01005881 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005882 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005883 else
5884 target = curproxy;
5885
5886 if (!target) {
5887 Alert("Proxy '%s': unable to find store table '%s'.\n",
5888 curproxy->id, mrule->table.name);
5889 cfgerr++;
5890 }
5891 else if (target->table.size == 0) {
5892 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5893 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5894 cfgerr++;
5895 }
Willy Tarreau12785782012-04-27 21:37:17 +02005896 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5897 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005898 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5899 cfgerr++;
5900 }
5901 else {
5902 free((void *)mrule->table.name);
5903 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005904 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005905 }
5906 }
5907
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005908 /* find the target table for 'tcp-request' layer 4 rules */
5909 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5910 struct proxy *target;
5911
Willy Tarreau56123282010-08-06 19:06:56 +02005912 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005913 continue;
5914
5915 if (trule->act_prm.trk_ctr.table.n)
5916 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5917 else
5918 target = curproxy;
5919
5920 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005921 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5922 curproxy->id, trule->act_prm.trk_ctr.table.n,
5923 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005924 cfgerr++;
5925 }
5926 else if (target->table.size == 0) {
5927 Alert("Proxy '%s': table '%s' used but not configured.\n",
5928 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5929 cfgerr++;
5930 }
5931 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005932 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 +02005933 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5934 cfgerr++;
5935 }
5936 else {
5937 free(trule->act_prm.trk_ctr.table.n);
5938 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005939 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005940 * to pass a list of counters to track and allocate them right here using
5941 * stktable_alloc_data_type().
5942 */
5943 }
5944 }
5945
Willy Tarreaud1f96522010-08-03 19:34:32 +02005946 /* find the target table for 'tcp-request' layer 6 rules */
5947 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5948 struct proxy *target;
5949
Willy Tarreau56123282010-08-06 19:06:56 +02005950 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005951 continue;
5952
5953 if (trule->act_prm.trk_ctr.table.n)
5954 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5955 else
5956 target = curproxy;
5957
5958 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005959 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5960 curproxy->id, trule->act_prm.trk_ctr.table.n,
5961 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005962 cfgerr++;
5963 }
5964 else if (target->table.size == 0) {
5965 Alert("Proxy '%s': table '%s' used but not configured.\n",
5966 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5967 cfgerr++;
5968 }
5969 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005970 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 +02005971 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5972 cfgerr++;
5973 }
5974 else {
5975 free(trule->act_prm.trk_ctr.table.n);
5976 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005977 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005978 * to pass a list of counters to track and allocate them right here using
5979 * stktable_alloc_data_type().
5980 */
5981 }
5982 }
5983
Emeric Brun32da3c42010-09-23 18:39:19 +02005984 if (curproxy->table.peers.name) {
5985 struct peers *curpeers = peers;
5986
5987 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5988 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5989 free((void *)curproxy->table.peers.name);
5990 curproxy->table.peers.p = peers;
5991 break;
5992 }
5993 }
5994
5995 if (!curpeers) {
5996 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5997 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005998 free((void *)curproxy->table.peers.name);
5999 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006000 cfgerr++;
6001 }
6002 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006003 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6004 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006005 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006006 cfgerr++;
6007 }
6008 }
6009
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006010 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006011 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006012 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6013 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6014 "proxy", curproxy->id);
6015 cfgerr++;
6016 goto out_uri_auth_compat;
6017 }
6018
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006019 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006020 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006021 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006022 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006023
Willy Tarreau95fa4692010-02-01 13:05:50 +01006024 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6025 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006026
6027 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006028 uri_auth_compat_req[i++] = "realm";
6029 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6030 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006031
Willy Tarreau95fa4692010-02-01 13:05:50 +01006032 uri_auth_compat_req[i++] = "unless";
6033 uri_auth_compat_req[i++] = "{";
6034 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6035 uri_auth_compat_req[i++] = "}";
6036 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006037
Willy Tarreauff011f22011-01-06 17:51:27 +01006038 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6039 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006040 cfgerr++;
6041 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006042 }
6043
Willy Tarreauff011f22011-01-06 17:51:27 +01006044 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006045
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006046 if (curproxy->uri_auth->auth_realm) {
6047 free(curproxy->uri_auth->auth_realm);
6048 curproxy->uri_auth->auth_realm = NULL;
6049 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006050
6051 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006052 }
6053out_uri_auth_compat:
6054
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006055 cfgerr += acl_find_targets(curproxy);
6056
Willy Tarreau2738a142006-07-08 17:28:09 +02006057 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006058 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006059 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006060 (!curproxy->timeout.connect ||
6061 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006062 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006063 " | While not properly invalid, you will certainly encounter various problems\n"
6064 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006065 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006066 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006067 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006068 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006069
Willy Tarreau1fa31262007-12-03 00:36:16 +01006070 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6071 * We must still support older configurations, so let's find out whether those
6072 * parameters have been set or must be copied from contimeouts.
6073 */
6074 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006075 if (!curproxy->timeout.tarpit ||
6076 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006077 /* tarpit timeout not set. We search in the following order:
6078 * default.tarpit, curr.connect, default.connect.
6079 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006080 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006081 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006082 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006083 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006084 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006085 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006086 }
6087 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006088 (!curproxy->timeout.queue ||
6089 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006090 /* queue timeout not set. We search in the following order:
6091 * default.queue, curr.connect, default.connect.
6092 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006093 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006094 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006095 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006096 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006097 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006098 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006099 }
6100 }
6101
Willy Tarreau1620ec32011-08-06 17:05:02 +02006102 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006103 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6104 curproxy->check_req = (char *)malloc(curproxy->check_len);
6105 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006106 }
6107
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006108 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006109 if (curproxy->nb_req_cap) {
6110 if (curproxy->mode == PR_MODE_HTTP) {
6111 curproxy->req_cap_pool = create_pool("ptrcap",
6112 curproxy->nb_req_cap * sizeof(char *),
6113 MEM_F_SHARED);
6114 } else {
6115 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6116 proxy_type_str(curproxy), curproxy->id);
6117 err_code |= ERR_WARN;
6118 curproxy->to_log &= ~LW_REQHDR;
6119 curproxy->nb_req_cap = 0;
6120 }
6121 }
6122
6123 if (curproxy->nb_rsp_cap) {
6124 if (curproxy->mode == PR_MODE_HTTP) {
6125 curproxy->rsp_cap_pool = create_pool("ptrcap",
6126 curproxy->nb_rsp_cap * sizeof(char *),
6127 MEM_F_SHARED);
6128 } else {
6129 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6130 proxy_type_str(curproxy), curproxy->id);
6131 err_code |= ERR_WARN;
6132 curproxy->to_log &= ~LW_REQHDR;
6133 curproxy->nb_rsp_cap = 0;
6134 }
6135 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006136
Willy Tarreau196729e2012-05-31 19:30:26 +02006137 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006138 if (!(curproxy->cap & PR_CAP_FE)) {
6139 if (curproxy->logformat_string != default_http_log_format &&
6140 curproxy->logformat_string != default_tcp_log_format &&
6141 curproxy->logformat_string != clf_http_log_format)
6142 free(curproxy->logformat_string);
6143 curproxy->logformat_string = NULL;
6144 }
6145
Willy Tarreau196729e2012-05-31 19:30:26 +02006146 if (curproxy->logformat_string)
6147 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6148
6149 if (curproxy->uniqueid_format_string)
6150 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6151
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 /* first, we will invert the servers list order */
6153 newsrv = NULL;
6154 while (curproxy->srv) {
6155 struct server *next;
6156
6157 next = curproxy->srv->next;
6158 curproxy->srv->next = newsrv;
6159 newsrv = curproxy->srv;
6160 if (!next)
6161 break;
6162 curproxy->srv = next;
6163 }
6164
Willy Tarreaudd701652010-05-25 23:03:02 +02006165 /* assign automatic UIDs to servers which don't have one yet */
6166 next_id = 1;
6167 newsrv = curproxy->srv;
6168 while (newsrv != NULL) {
6169 if (!newsrv->puid) {
6170 /* server ID not set, use automatic numbering with first
6171 * spare entry starting with next_svid.
6172 */
6173 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6174 newsrv->conf.id.key = newsrv->puid = next_id;
6175 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6176 }
6177 next_id++;
6178 newsrv = newsrv->next;
6179 }
6180
Willy Tarreau20697042007-11-15 23:26:18 +01006181 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006182 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183
Willy Tarreau62c3be22012-01-20 13:12:32 +01006184 /*
6185 * If this server supports a maxconn parameter, it needs a dedicated
6186 * tasks to fill the emptied slots when a connection leaves.
6187 * Also, resolve deferred tracking dependency if needed.
6188 */
6189 newsrv = curproxy->srv;
6190 while (newsrv != NULL) {
6191 if (newsrv->minconn > newsrv->maxconn) {
6192 /* Only 'minconn' was specified, or it was higher than or equal
6193 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6194 * this will avoid further useless expensive computations.
6195 */
6196 newsrv->maxconn = newsrv->minconn;
6197 } else if (newsrv->maxconn && !newsrv->minconn) {
6198 /* minconn was not specified, so we set it to maxconn */
6199 newsrv->minconn = newsrv->maxconn;
6200 }
6201
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006202#ifdef USE_OPENSSL
6203#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6204#define SSL_OP_NO_COMPRESSION 0
6205#endif
6206#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6207#define SSL_MODE_RELEASE_BUFFERS 0
6208#endif
6209#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6210#define SSL_OP_NO_COMPRESSION 0
6211#endif
6212 if (newsrv->use_ssl) {
6213 int ssloptions =
6214 SSL_OP_ALL | /* all known workarounds for bugs */
6215 SSL_OP_NO_SSLv2 |
6216 SSL_OP_NO_COMPRESSION;
6217 int sslmode =
6218 SSL_MODE_ENABLE_PARTIAL_WRITE |
6219 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6220 SSL_MODE_RELEASE_BUFFERS;
6221
6222 /* Initiate SSL context for current server */
6223 newsrv->ssl_ctx.reused_sess = NULL;
6224 newsrv->data = &ssl_sock;
6225 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6226 if(!newsrv->ssl_ctx.ctx) {
6227
6228 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6229 proxy_type_str(curproxy), curproxy->id,
6230 newsrv->id);
6231 cfgerr++;
6232 goto next_srv;
6233 }
6234
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006235 if (newsrv->ssl_ctx.nosslv3)
6236 ssloptions |= SSL_OP_NO_SSLv3;
6237 if (newsrv->ssl_ctx.notlsv1)
6238 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006239 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6240 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6241 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6242 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006243 if (newsrv->ssl_ctx.ciphers &&
6244 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6245 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6246 curproxy->id, newsrv->id,
6247 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6248 cfgerr++;
6249 goto next_srv;
6250 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006251 }
6252#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006253 if (newsrv->trackit) {
6254 struct proxy *px;
6255 struct server *srv;
6256 char *pname, *sname;
6257
6258 pname = newsrv->trackit;
6259 sname = strrchr(pname, '/');
6260
6261 if (sname)
6262 *sname++ = '\0';
6263 else {
6264 sname = pname;
6265 pname = NULL;
6266 }
6267
6268 if (pname) {
6269 px = findproxy(pname, PR_CAP_BE);
6270 if (!px) {
6271 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6272 proxy_type_str(curproxy), curproxy->id,
6273 newsrv->id, pname);
6274 cfgerr++;
6275 goto next_srv;
6276 }
6277 } else
6278 px = curproxy;
6279
6280 srv = findserver(px, sname);
6281 if (!srv) {
6282 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6283 proxy_type_str(curproxy), curproxy->id,
6284 newsrv->id, sname);
6285 cfgerr++;
6286 goto next_srv;
6287 }
6288
6289 if (!(srv->state & SRV_CHECKED)) {
6290 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6291 "tracking as it does not have checks enabled.\n",
6292 proxy_type_str(curproxy), curproxy->id,
6293 newsrv->id, px->id, srv->id);
6294 cfgerr++;
6295 goto next_srv;
6296 }
6297
6298 if (curproxy != px &&
6299 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6300 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6301 "tracking: disable-on-404 option inconsistency.\n",
6302 proxy_type_str(curproxy), curproxy->id,
6303 newsrv->id, px->id, srv->id);
6304 cfgerr++;
6305 goto next_srv;
6306 }
6307
6308 /* if the other server is forced disabled, we have to do the same here */
6309 if (srv->state & SRV_MAINTAIN) {
6310 newsrv->state |= SRV_MAINTAIN;
6311 newsrv->state &= ~SRV_RUNNING;
6312 newsrv->health = 0;
6313 }
6314
6315 newsrv->track = srv;
6316 newsrv->tracknext = srv->tracknext;
6317 srv->tracknext = newsrv;
6318
6319 free(newsrv->trackit);
6320 newsrv->trackit = NULL;
6321 }
6322 next_srv:
6323 newsrv = newsrv->next;
6324 }
6325
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006326 /* We have to initialize the server lookup mechanism depending
6327 * on what LB algorithm was choosen.
6328 */
6329
6330 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6331 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6332 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006333 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6334 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6335 init_server_map(curproxy);
6336 } else {
6337 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6338 fwrr_init_server_groups(curproxy);
6339 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006340 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006341
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006342 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006343 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6344 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6345 fwlc_init_server_tree(curproxy);
6346 } else {
6347 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6348 fas_init_server_tree(curproxy);
6349 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006350 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006351
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006352 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006353 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6354 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6355 chash_init_server_tree(curproxy);
6356 } else {
6357 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6358 init_server_map(curproxy);
6359 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006360 break;
6361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362
6363 if (curproxy->options & PR_O_LOGASAP)
6364 curproxy->to_log &= ~LW_BYTES;
6365
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006366 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006367 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006368 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6369 proxy_type_str(curproxy), curproxy->id);
6370 err_code |= ERR_WARN;
6371 }
6372
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006373 if (curproxy->mode != PR_MODE_HTTP) {
6374 int optnum;
6375
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006376 if (curproxy->uri_auth) {
6377 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6378 proxy_type_str(curproxy), curproxy->id);
6379 err_code |= ERR_WARN;
6380 curproxy->uri_auth = NULL;
6381 }
6382
Willy Tarreau87cf5142011-08-19 22:57:24 +02006383 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006384 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6385 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6386 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006387 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006388 }
6389
6390 if (curproxy->options & PR_O_ORGTO) {
6391 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6392 "originalto", proxy_type_str(curproxy), curproxy->id);
6393 err_code |= ERR_WARN;
6394 curproxy->options &= ~PR_O_ORGTO;
6395 }
6396
6397 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6398 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6399 (curproxy->cap & cfg_opts[optnum].cap) &&
6400 (curproxy->options & cfg_opts[optnum].val)) {
6401 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6402 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6403 err_code |= ERR_WARN;
6404 curproxy->options &= ~cfg_opts[optnum].val;
6405 }
6406 }
6407
6408 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6409 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6410 (curproxy->cap & cfg_opts2[optnum].cap) &&
6411 (curproxy->options2 & cfg_opts2[optnum].val)) {
6412 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6413 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6414 err_code |= ERR_WARN;
6415 curproxy->options2 &= ~cfg_opts2[optnum].val;
6416 }
6417 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006418
Willy Tarreauefa5f512010-03-30 20:13:29 +02006419#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006420 if (curproxy->bind_hdr_occ) {
6421 curproxy->bind_hdr_occ = 0;
6422 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6423 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6424 err_code |= ERR_WARN;
6425 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006426#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006427 }
6428
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006430 * ensure that we're not cross-dressing a TCP server into HTTP.
6431 */
6432 newsrv = curproxy->srv;
6433 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006434 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006435 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6436 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006437 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006438 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006439
Willy Tarreau0cec3312011-10-31 13:49:26 +01006440 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6441 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6442 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6443 err_code |= ERR_WARN;
6444 }
6445
Willy Tarreauefa5f512010-03-30 20:13:29 +02006446#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006447 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6448 newsrv->bind_hdr_occ = 0;
6449 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6450 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6451 err_code |= ERR_WARN;
6452 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006453#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006454 newsrv = newsrv->next;
6455 }
6456
Willy Tarreauc1a21672009-08-16 22:37:44 +02006457 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006458 curproxy->accept = frontend_accept;
6459
Willy Tarreauc1a21672009-08-16 22:37:44 +02006460 if (curproxy->tcp_req.inspect_delay ||
6461 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006462 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006463
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006464 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006465 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006466 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006467 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006468
6469 /* both TCP and HTTP must check switching rules */
6470 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6471 }
6472
6473 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006474 if (curproxy->tcp_req.inspect_delay ||
6475 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6476 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6477
Emeric Brun97679e72010-09-23 17:56:44 +02006478 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6479 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6480
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006481 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006482 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006483 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006484 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006485
6486 /* If the backend does requires RDP cookie persistence, we have to
6487 * enable the corresponding analyser.
6488 */
6489 if (curproxy->options2 & PR_O2_RDPC_PRST)
6490 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6491 }
6492
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006493 listener = NULL;
6494 while (curproxy->listen) {
6495 struct listener *next;
6496
6497 next = curproxy->listen->next;
6498 curproxy->listen->next = listener;
6499 listener = curproxy->listen;
6500
6501 if (!next)
6502 break;
6503
6504 curproxy->listen = next;
6505 }
6506
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006507 /* Configure SSL for each bind line.
6508 * Note: if configuration fails at some point, the ->ctx member
6509 * remains NULL so that listeners can later detach.
6510 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006511 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6512 if (!bind_conf->is_ssl)
6513 continue;
6514#ifdef USE_OPENSSL
6515 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006516 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006517 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006518 cfgerr++;
6519 continue;
6520 }
6521
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006522 if (shared_context_init(global.tune.sslcachesize) < 0) {
6523 Alert("Unable to allocate SSL session cache.\n");
6524 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006525 continue;
6526 }
6527
Emeric Brunfc0421f2012-09-07 17:30:07 +02006528 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006529 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006530#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006531 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006532
Willy Tarreaue6b98942007-10-29 01:09:36 +01006533 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006534 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006535 listener = curproxy->listen;
6536 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006537 if (!listener->luid) {
6538 /* listener ID not set, use automatic numbering with first
6539 * spare entry starting with next_luid.
6540 */
6541 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6542 listener->conf.id.key = listener->luid = next_id;
6543 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006544 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006545 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006546
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006547 /* enable separate counters */
6548 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6549 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6550 if (!listener->name) {
6551 sprintf(trash, "sock-%d", listener->luid);
6552 listener->name = strdup(trash);
6553 }
6554 }
Emeric Brun6e159292012-05-18 16:32:13 +02006555#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006556 if (listener->bind_conf->is_ssl && listener->bind_conf->default_ctx)
6557 listener->data = &ssl_sock; /* SSL data layer */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006558#endif
Willy Tarreaue6b98942007-10-29 01:09:36 +01006559 if (curproxy->options & PR_O_TCP_NOLING)
6560 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006561 if (!listener->maxconn)
6562 listener->maxconn = curproxy->maxconn;
6563 if (!listener->backlog)
6564 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006565 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006566 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006567 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006568 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006569 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006570
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006571 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6572 listener->options |= LI_O_TCP_RULES;
6573
Willy Tarreaude3041d2010-05-31 10:56:17 +02006574 if (curproxy->mon_mask.s_addr)
6575 listener->options |= LI_O_CHK_MONNET;
6576
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006577 /* smart accept mode is automatic in HTTP mode */
6578 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006579 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006580 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6581 listener->options |= LI_O_NOQUICKACK;
6582
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006583 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006584 listener = listener->next;
6585 }
6586
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006587 /* Release unused SSL configs */
6588 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6589 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006590 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006591#ifdef USE_OPENSSL
6592 ssl_sock_free_all_ctx(bind_conf);
6593 free(bind_conf->ciphers);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006594#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006595 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006596
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006597 /* Check multi-process mode compatibility for the current proxy */
6598 if (global.nbproc > 1) {
6599 int nbproc = 0;
6600 if (curproxy->bind_proc) {
6601 int proc;
6602 for (proc = 0; proc < global.nbproc; proc++) {
6603 if (curproxy->bind_proc & (1 << proc)) {
6604 nbproc++;
6605 }
6606 }
6607 } else {
6608 nbproc = global.nbproc;
6609 }
6610 if (curproxy->table.peers.name) {
6611 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6612 curproxy->id);
6613 cfgerr++;
6614 }
6615 if (nbproc > 1) {
6616 if (curproxy->uri_auth) {
6617 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6618 curproxy->id);
6619 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6620 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6621 curproxy->id);
6622 }
6623 }
6624 if (curproxy->appsession_name) {
6625 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6626 curproxy->id);
6627 }
6628 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6629 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6630 curproxy->id);
6631 }
6632 }
6633 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006634
6635 /* create the task associated with the proxy */
6636 curproxy->task = task_new();
6637 if (curproxy->task) {
6638 curproxy->task->context = curproxy;
6639 curproxy->task->process = manage_proxy;
6640 /* no need to queue, it will be done automatically if some
6641 * listener gets limited.
6642 */
6643 curproxy->task->expire = TICK_ETERNITY;
6644 } else {
6645 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6646 curproxy->id);
6647 cfgerr++;
6648 }
6649
Willy Tarreaubaaee002006-06-26 02:48:02 +02006650 curproxy = curproxy->next;
6651 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006652
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006653 /* Check multi-process mode compatibility */
6654 if (global.nbproc > 1) {
6655 if (global.stats_fe) {
6656 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6657 }
6658 }
6659
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6661 struct auth_users *curuser;
6662 int g;
6663
6664 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6665 unsigned int group_mask = 0;
6666 char *group = NULL;
6667
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006668 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006669 continue;
6670
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006671 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006672
6673 for (g = 0; g < curuserlist->grpcnt; g++)
6674 if (!strcmp(curuserlist->groups[g], group))
6675 break;
6676
6677 if (g == curuserlist->grpcnt) {
6678 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6679 curuserlist->name, group, curuser->user);
6680 err_code |= ERR_ALERT | ERR_FATAL;
6681 goto out;
6682 }
6683
6684 group_mask |= (1 << g);
6685 }
6686
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006687 free(curuser->u.groups);
6688 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689 }
6690
6691 for (g = 0; g < curuserlist->grpcnt; g++) {
6692 char *user = NULL;
6693
6694 if (!curuserlist->groupusers[g])
6695 continue;
6696
6697 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6698 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6699 if (!strcmp(curuser->user, user))
6700 break;
6701
6702 if (!curuser) {
6703 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6704 curuserlist->name, user, curuserlist->groups[g]);
6705 err_code |= ERR_ALERT | ERR_FATAL;
6706 goto out;
6707 }
6708
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006709 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006710 }
6711
6712 free(curuserlist->groupusers[g]);
6713 }
6714
6715 free(curuserlist->groupusers);
6716
6717#ifdef DEBUG_AUTH
6718 for (g = 0; g < curuserlist->grpcnt; g++) {
6719 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6720
6721 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006722 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006723 fprintf(stderr, " %s", curuser->user);
6724 }
6725
6726 fprintf(stderr, "\n");
6727 }
6728#endif
6729
Willy Tarreaufbb78422011-06-05 15:38:35 +02006730 }
6731
6732 /* automatically compute fullconn if not set. We must not do it in the
6733 * loop above because cross-references are not yet fully resolved.
6734 */
6735 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6736 /* If <fullconn> is not set, let's set it to 10% of the sum of
6737 * the possible incoming frontend's maxconns.
6738 */
6739 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6740 struct proxy *fe;
6741 int total = 0;
6742
6743 /* sum up the number of maxconns of frontends which
6744 * reference this backend at least once or which are
6745 * the same one ('listen').
6746 */
6747 for (fe = proxy; fe; fe = fe->next) {
6748 struct switching_rule *rule;
6749 struct hdr_exp *exp;
6750 int found = 0;
6751
6752 if (!(fe->cap & PR_CAP_FE))
6753 continue;
6754
6755 if (fe == curproxy) /* we're on a "listen" instance */
6756 found = 1;
6757
6758 if (fe->defbe.be == curproxy) /* "default_backend" */
6759 found = 1;
6760
6761 /* check if a "use_backend" rule matches */
6762 if (!found) {
6763 list_for_each_entry(rule, &fe->switching_rules, list) {
6764 if (rule->be.backend == curproxy) {
6765 found = 1;
6766 break;
6767 }
6768 }
6769 }
6770
6771 /* check if a "reqsetbe" rule matches */
6772 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6773 if (exp->action == ACT_SETBE &&
6774 (struct proxy *)exp->replace == curproxy) {
6775 found = 1;
6776 break;
6777 }
6778 }
6779
6780 /* now we've checked all possible ways to reference a backend
6781 * from a frontend.
6782 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006783 if (!found)
6784 continue;
6785 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006786 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006787 /* we have the sum of the maxconns in <total>. We only
6788 * keep 10% of that sum to set the default fullconn, with
6789 * a hard minimum of 1 (to avoid a divide by zero).
6790 */
6791 curproxy->fullconn = (total + 9) / 10;
6792 if (!curproxy->fullconn)
6793 curproxy->fullconn = 1;
6794 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006795 }
6796
Willy Tarreau056f5682010-06-06 15:51:11 +02006797 /* initialize stick-tables on backend capable proxies. This must not
6798 * be done earlier because the data size may be discovered while parsing
6799 * other proxies.
6800 */
6801 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006802 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006803
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006804 /*
6805 * Recount currently required checks.
6806 */
6807
6808 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6809 int optnum;
6810
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006811 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6812 if (curproxy->options & cfg_opts[optnum].val)
6813 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006814
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006815 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6816 if (curproxy->options2 & cfg_opts2[optnum].val)
6817 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006818 }
6819
Willy Tarreau122541c2011-09-07 21:24:49 +02006820 if (peers) {
6821 struct peers *curpeers = peers, **last;
6822 struct peer *p, *pb;
6823
6824 /* Remove all peers sections which don't have a valid listener.
6825 * This can happen when a peers section is never referenced and
6826 * does not contain a local peer.
6827 */
6828 last = &peers;
6829 while (*last) {
6830 curpeers = *last;
6831 if (curpeers->peers_fe) {
6832 last = &curpeers->next;
6833 continue;
6834 }
6835
6836 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6837 curpeers->id, localpeer);
6838
6839 p = curpeers->remote;
6840 while (p) {
6841 pb = p->next;
6842 free(p->id);
6843 free(p);
6844 p = pb;
6845 }
6846
6847 /* Destroy and unlink this curpeers section.
6848 * Note: curpeers is backed up into *last.
6849 */
6850 free(curpeers->id);
6851 curpeers = curpeers->next;
6852 free(*last);
6853 *last = curpeers;
6854 }
6855 }
6856
Willy Tarreauac1932d2011-10-24 19:14:41 +02006857 if (!global.tune.max_http_hdr)
6858 global.tune.max_http_hdr = MAX_HTTP_HDR;
6859
Willy Tarreau34eb6712011-10-24 18:15:04 +02006860 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006861 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006862 MEM_F_SHARED);
6863
Willy Tarreaubb925012009-07-23 13:36:36 +02006864 if (cfgerr > 0)
6865 err_code |= ERR_ALERT | ERR_FATAL;
6866 out:
6867 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006868}
6869
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006870/*
6871 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6872 * parsing sessions.
6873 */
6874void cfg_register_keywords(struct cfg_kw_list *kwl)
6875{
6876 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6877}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006878
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006879/*
6880 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6881 */
6882void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6883{
6884 LIST_DEL(&kwl->list);
6885 LIST_INIT(&kwl->list);
6886}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006887
6888/*
6889 * Local variables:
6890 * c-indent-level: 8
6891 * c-basic-offset: 8
6892 * End:
6893 */