blob: 034fe62209e4c097844add9948cc71068a1cafd6 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
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 Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.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 Tarreau0f772532006-12-23 20:51:41 +010046#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010060#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010062#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063
64
Willy Tarreauf3c69202006-07-09 16:42:34 +020065/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
66 * ssl-hello-chk option to ensure that the remote server speaks SSL.
67 *
68 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
69 */
70const char sslv3_client_hello_pkt[] = {
71 "\x16" /* ContentType : 0x16 = Hanshake */
72 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
73 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
74 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
75 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
76 "\x03\x00" /* Hello Version : 0x0300 = v3 */
77 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
78 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
79 "\x00" /* Session ID length : empty (no session ID) */
80 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
81 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
82 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
83 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
84 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
85 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
86 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
87 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
88 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
89 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
90 "\x00\x38" "\x00\x39" "\x00\x3A"
91 "\x01" /* Compression Length : 0x01 = 1 byte for types */
92 "\x00" /* Compression Type : 0x00 = NULL compression */
93};
94
Willy Tarreau3842f002009-06-14 11:39:52 +020095/* various keyword modifiers */
96enum kw_mod {
97 KWM_STD = 0, /* normal */
98 KWM_NO, /* "no" prefixed before the keyword */
99 KWM_DEF, /* "default" prefixed before the keyword */
100};
101
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100103struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104 const char *name;
105 unsigned int val;
106 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100107 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100108 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100109};
110
111/* proxy->options */
112static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100114 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
115 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
116 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
117 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
118 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
119 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
120 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
124 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
126 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
127 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
128 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
129 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100130#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100132#endif
133
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135};
136
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100137/* proxy->options2 */
138static const struct cfg_opt cfg_opts2[] =
139{
140#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
142 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
143 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
146 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
147 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
148 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
149 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
150 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
151 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
152 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
153 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200155 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100156 { NULL, 0, 0, 0 }
157};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200158
Willy Tarreau6daf3432008-01-22 16:44:08 +0100159static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200160static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
161int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100162int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200164/* List head of all known configuration keywords */
165static struct cfg_kw_list cfg_keywords = {
166 .list = LIST_HEAD_INIT(cfg_keywords.list)
167};
168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/*
170 * converts <str> to a list of listeners which are dynamically allocated.
171 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
172 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
173 * - <port> is a numerical port from 1 to 65535 ;
174 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
175 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200176 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200178static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179{
180 struct listener *l;
181 char *c, *next, *range, *dupstr;
182 int port, end;
183
184 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 while (next && *next) {
187 struct sockaddr_storage ss;
188
189 str = next;
190 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100191 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192 *next++ = 0;
193 }
194
Emeric Bruned760922010-10-22 17:59:25 +0200195 if (*str == '/') {
196 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
197 /* so compute max path */
198 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
199 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 +0200200
Emeric Bruned760922010-10-22 17:59:25 +0200201 if (strlen(str) > max_path_len) {
202 Alert("Socket path '%s' too long (max %d)\n", str, max_path_len);
203 goto fail;
204 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200207 ss.ss_family = AF_UNIX;
208 if (global.unix_bind.prefix) {
209 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
210 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211 }
Emeric Bruned760922010-10-22 17:59:25 +0200212 else {
213 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
214 }
215 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 }
217 else {
Emeric Bruned760922010-10-22 17:59:25 +0200218 /* 2) look for the addr/port delimiter, it's the last colon. */
219 if ((range = strrchr(str, ':')) == NULL) {
220 Alert("Missing port number: '%s'\n", str);
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 }
Emeric Bruned760922010-10-22 17:59:25 +0200223
224 *range++ = 0;
225
226 if (strrchr(str, ':') != NULL) {
227 /* IPv6 address contains ':' */
228 memset(&ss, 0, sizeof(ss));
229 ss.ss_family = AF_INET6;
230
231 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
232 Alert("Invalid server address: '%s'\n", str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 goto fail;
234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 }
Emeric Bruned760922010-10-22 17:59:25 +0200236 else {
237 memset(&ss, 0, sizeof(ss));
238 ss.ss_family = AF_INET;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
Emeric Bruned760922010-10-22 17:59:25 +0200240 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
241 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
242 }
243 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
244 struct hostent *he;
245
246 if ((he = gethostbyname(str)) == NULL) {
247 Alert("Invalid server name: '%s'\n", str);
248 goto fail;
249 }
250 else
251 ((struct sockaddr_in *)&ss)->sin_addr =
252 *(struct in_addr *) *(he->h_addr_list);
253 }
254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Emeric Bruned760922010-10-22 17:59:25 +0200256 /* 3) look for the port-end delimiter */
257 if ((c = strchr(range, '-')) != NULL) {
258 *c++ = 0;
259 end = atol(c);
260 }
261 else {
262 end = atol(range);
263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
Emeric Bruned760922010-10-22 17:59:25 +0200265 port = atol(range);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266
Emeric Bruned760922010-10-22 17:59:25 +0200267 if (port < 1 || port > 65535) {
268 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
269 goto fail;
270 }
271
272 if (end < 1 || end > 65535) {
273 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
274 goto fail;
275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 }
277
278 for (; port <= end; port++) {
279 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280 l->next = curproxy->listen;
281 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282
283 l->fd = -1;
284 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 l->state = LI_INIT;
286
Emeric Bruned760922010-10-22 17:59:25 +0200287 if(ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 tcpv4_add_listener(l);
290 }
Emeric Bruned760922010-10-22 17:59:25 +0200291 else if (ss.ss_family == AF_INET6) {
292 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
293 tcpv6_add_listener(l);
294 }
295 else {
296 l->perm.ux.gid = l->perm.ux.uid = -1;
297 l->perm.ux.mode = 0;
298 uxst_add_listener(l);
299 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200301 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100302 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 } /* end for(port) */
304 } /* end while(next) */
305 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200306 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307 fail:
308 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310}
311
Willy Tarreau977b8e42006-12-29 14:19:17 +0100312/*
313 * Sends a warning if proxy <proxy> does not have at least one of the
314 * capabilities in <cap>. An optionnal <hint> may be added at the end
315 * of the warning to help the user. Returns 1 if a warning was emitted
316 * or 0 if the condition is valid.
317 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100318int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100319{
320 char *msg;
321
322 switch (cap) {
323 case PR_CAP_BE: msg = "no backend"; break;
324 case PR_CAP_FE: msg = "no frontend"; break;
325 case PR_CAP_RS: msg = "no ruleset"; break;
326 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
327 default: msg = "not enough"; break;
328 }
329
330 if (!(proxy->cap & cap)) {
331 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100332 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100333 return 1;
334 }
335 return 0;
336}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200337
Willy Tarreau61d18892009-03-31 10:49:21 +0200338/* Report a warning if a rule is placed after a 'block' rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (!LIST_ISEMPTY(&proxy->block_cond)) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqrewrite rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
356 if (proxy->req_exp) {
357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a reqadd rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100369 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a redirect rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* Report a warning if a rule is placed after a 'use_backend' rule.
391 * Return 1 if the warning has been emitted, otherwise 0.
392 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
396 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
397 file, line, arg);
398 return 1;
399 }
400 return 0;
401}
402
403/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
407 warnif_rule_after_reqadd(proxy, file, line, arg) ||
408 warnif_rule_after_redirect(proxy, file, line, arg) ||
409 warnif_rule_after_use_backend(proxy, file, line, arg);
410}
411
412/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100413int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200414{
415 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
416 warnif_rule_after_redirect(proxy, file, line, arg) ||
417 warnif_rule_after_use_backend(proxy, file, line, arg);
418}
419
420/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100421int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200422{
423 return warnif_rule_after_redirect(proxy, file, line, arg) ||
424 warnif_rule_after_use_backend(proxy, file, line, arg);
425}
426
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100427/* Report it if a request ACL condition uses some response-only parameters. It
428 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
429 * Note that <cond> may be NULL and then will be ignored.
430 */
431static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
432{
433 struct acl *acl;
434
435 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
436 return 0;
437
438 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
439 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
440 file, line, acl ? acl->name : "(unknown)");
441 return ERR_WARN;
442}
443
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100444/* Report it if a request ACL condition uses some request-only volatile parameters.
445 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
446 * Note that <cond> may be NULL and then will be ignored.
447 */
448static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
449{
450 struct acl *acl;
451
452 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
453 return 0;
454
455 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
456 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
457 file, line, acl ? acl->name : "(unknown)");
458 return ERR_WARN;
459}
460
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100461
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200463 * parse a line in a <global> section. Returns the error code, 0 if OK, or
464 * any combination of :
465 * - ERR_ABORT: must abort ASAP
466 * - ERR_FATAL: we can continue parsing but not start the service
467 * - ERR_WARN: a warning has been emitted
468 * - ERR_ALERT: an alert has been emitted
469 * Only the two first ones can stop processing, the two others are just
470 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200472int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473{
Willy Tarreau058e9072009-07-20 09:30:05 +0200474 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475
476 if (!strcmp(args[0], "global")) { /* new section */
477 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
480 else if (!strcmp(args[0], "daemon")) {
481 global.mode |= MODE_DAEMON;
482 }
483 else if (!strcmp(args[0], "debug")) {
484 global.mode |= MODE_DEBUG;
485 }
486 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100487 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200489 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100490 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200491 }
492 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100493 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100496 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100498 else if (!strcmp(args[0], "nosplice")) {
499 global.tune.options &= ~GTUNE_USE_SPLICE;
500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200501 else if (!strcmp(args[0], "quiet")) {
502 global.mode |= MODE_QUIET;
503 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200504 else if (!strcmp(args[0], "tune.maxpollevents")) {
505 if (global.tune.maxpollevents != 0) {
506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT;
508 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200509 }
510 if (*(args[1]) == 0) {
511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200514 }
515 global.tune.maxpollevents = atol(args[1]);
516 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100517 else if (!strcmp(args[0], "tune.maxaccept")) {
518 if (global.tune.maxaccept != 0) {
519 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT;
521 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100522 }
523 if (*(args[1]) == 0) {
524 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100527 }
528 global.tune.maxaccept = atol(args[1]);
529 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200530 else if (!strcmp(args[0], "tune.chksize")) {
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.chksize = atol(args[1]);
537 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200538 else if (!strcmp(args[0], "tune.bufsize")) {
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT | ERR_FATAL;
542 goto out;
543 }
544 global.tune.bufsize = atol(args[1]);
545 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
546 global.tune.maxrewrite = global.tune.bufsize / 2;
547 }
548 else if (!strcmp(args[0], "tune.maxrewrite")) {
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
553 }
554 global.tune.maxrewrite = atol(args[1]);
555 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
556 global.tune.maxrewrite = global.tune.bufsize / 2;
557 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100558 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
559 if (global.tune.client_rcvbuf != 0) {
560 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.tune.client_rcvbuf = atol(args[1]);
570 }
571 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
572 if (global.tune.server_rcvbuf != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT;
575 goto out;
576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.server_rcvbuf = atol(args[1]);
583 }
584 else if (!strcmp(args[0], "tune.sndbuf.client")) {
585 if (global.tune.client_sndbuf != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT;
588 goto out;
589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
594 }
595 global.tune.client_sndbuf = atol(args[1]);
596 }
597 else if (!strcmp(args[0], "tune.sndbuf.server")) {
598 if (global.tune.server_sndbuf != 0) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT;
601 goto out;
602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.server_sndbuf = atol(args[1]);
609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 else if (!strcmp(args[0], "uid")) {
611 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200612 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200613 err_code |= ERR_ALERT;
614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620 }
621 global.uid = atol(args[1]);
622 }
623 else if (!strcmp(args[0], "gid")) {
624 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200625 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 }
634 global.gid = atol(args[1]);
635 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200636 /* user/group name handling */
637 else if (!strcmp(args[0], "user")) {
638 struct passwd *ha_user;
639 if (global.uid != 0) {
640 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200641 err_code |= ERR_ALERT;
642 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200643 }
644 errno = 0;
645 ha_user = getpwnam(args[1]);
646 if (ha_user != NULL) {
647 global.uid = (int)ha_user->pw_uid;
648 }
649 else {
650 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200651 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200652 }
653 }
654 else if (!strcmp(args[0], "group")) {
655 struct group *ha_group;
656 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200657 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
659 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 errno = 0;
662 ha_group = getgrnam(args[1]);
663 if (ha_group != NULL) {
664 global.gid = (int)ha_group->gr_gid;
665 }
666 else {
667 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200669 }
670 }
671 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672 else if (!strcmp(args[0], "nbproc")) {
673 if (global.nbproc != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683 global.nbproc = atol(args[1]);
684 }
685 else if (!strcmp(args[0], "maxconn")) {
686 if (global.maxconn != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 }
696 global.maxconn = atol(args[1]);
697#ifdef SYSTEM_MAXCONN
698 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
699 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
700 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200702 }
703#endif /* SYSTEM_MAXCONN */
704 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100705 else if (!strcmp(args[0], "maxpipes")) {
706 if (global.maxpipes != 0) {
707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 err_code |= ERR_ALERT;
709 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100710 }
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100715 }
716 global.maxpipes = atol(args[1]);
717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 else if (!strcmp(args[0], "ulimit-n")) {
719 if (global.rlimit_nofile != 0) {
720 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT;
722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 }
724 if (*(args[1]) == 0) {
725 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 }
729 global.rlimit_nofile = atol(args[1]);
730 }
731 else if (!strcmp(args[0], "chroot")) {
732 if (global.chroot != NULL) {
733 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200741 }
742 global.chroot = strdup(args[1]);
743 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200744 else if (!strcmp(args[0], "description")) {
745 int i, len=0;
746 char *d;
747
748 if (!*args[1]) {
749 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
750 file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754
755 for(i=1; *args[i]; i++)
756 len += strlen(args[i])+1;
757
758 if (global.desc)
759 free(global.desc);
760
761 global.desc = d = (char *)calloc(1, len);
762
763 d += sprintf(d, "%s", args[1]);
764 for(i=2; *args[i]; i++)
765 d += sprintf(d, " %s", args[i]);
766 }
767 else if (!strcmp(args[0], "node")) {
768 int i;
769 char c;
770
771 for (i=0; args[1][i]; i++) {
772 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100773 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
774 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200775 break;
776 }
777
778 if (!i || args[1][i]) {
779 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
780 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
781 file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785
786 if (global.node)
787 free(global.node);
788
789 global.node = strdup(args[1]);
790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200791 else if (!strcmp(args[0], "pidfile")) {
792 if (global.pidfile != NULL) {
793 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200794 err_code |= ERR_ALERT;
795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200796 }
797 if (*(args[1]) == 0) {
798 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 }
802 global.pidfile = strdup(args[1]);
803 }
Emeric Bruned760922010-10-22 17:59:25 +0200804 else if (!strcmp(args[0], "unix-bind")) {
805 int cur_arg = 1;
806 while (*(args[cur_arg])) {
807 if (!strcmp(args[cur_arg], "prefix")) {
808 if (global.unix_bind.prefix != NULL) {
809 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
810 err_code |= ERR_ALERT;
811 cur_arg += 2;
812 continue;
813 }
814
815 if (*(args[cur_arg+1]) == 0) {
816 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.unix_bind.prefix = strdup(args[cur_arg+1]);
821 cur_arg += 2;
822 continue;
823 }
824
825 if (!strcmp(args[cur_arg], "mode")) {
826
827 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
828 cur_arg += 2;
829 continue;
830 }
831
832 if (!strcmp(args[cur_arg], "uid")) {
833
834 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
835 cur_arg += 2;
836 continue;
837 }
838
839 if (!strcmp(args[cur_arg], "gid")) {
840
841 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
842 cur_arg += 2;
843 continue;
844 }
845
846 if (!strcmp(args[cur_arg], "user")) {
847 struct passwd *user;
848
849 user = getpwnam(args[cur_arg + 1]);
850 if (!user) {
851 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
852 file, linenum, args[0], args[cur_arg + 1 ]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856
857 global.unix_bind.ux.uid = user->pw_uid;
858 cur_arg += 2;
859 continue;
860 }
861
862 if (!strcmp(args[cur_arg], "group")) {
863 struct group *group;
864
865 group = getgrnam(args[cur_arg + 1]);
866 if (!group) {
867 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
868 file, linenum, args[0], args[cur_arg + 1 ]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872
873 global.unix_bind.ux.gid = group->gr_gid;
874 cur_arg += 2;
875 continue;
876 }
877
878 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
879 file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100885 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200886 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887
888 if (*(args[1]) == 0 || *(args[2]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893
894 facility = get_log_facility(args[2]);
895 if (facility < 0) {
896 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200897 err_code |= ERR_ALERT | ERR_FATAL;
898 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899 }
900
901 level = 7; /* max syslog level = debug */
902 if (*(args[3])) {
903 level = get_log_level(args[3]);
904 if (level < 0) {
905 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200906 err_code |= ERR_ALERT | ERR_FATAL;
907 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 }
910
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200911 minlvl = 0; /* limit syslog level to this level (emerg) */
912 if (*(args[4])) {
913 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200914 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200915 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200918 }
919 }
920
Robert Tsai81ae1952007-12-05 10:47:29 +0100921 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100922 struct sockaddr_un *sk = str2sun(args[1]);
923 if (!sk) {
924 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
925 args[1], (int)sizeof(sk->sun_path) - 1);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
928 }
929 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100930 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100931 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100932 struct sockaddr_in *sk = str2sa(args[1]);
933 if (!sk) {
934 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100939 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100940 if (!logsrv.u.in.sin_port)
941 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943
944 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100945 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 global.logfac1 = facility;
947 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200948 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100951 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 global.logfac2 = facility;
953 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200954 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
956 else {
957 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200960 }
961 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
962 if (global.spread_checks != 0) {
963 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT;
965 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200966 }
967 if (*(args[1]) == 0) {
968 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200971 }
972 global.spread_checks = atol(args[1]);
973 if (global.spread_checks < 0 || global.spread_checks > 50) {
974 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 }
978 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200979 struct cfg_kw_list *kwl;
980 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200981 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200982
983 list_for_each_entry(kwl, &cfg_keywords.list, list) {
984 for (index = 0; kwl->kw[index].kw != NULL; index++) {
985 if (kwl->kw[index].section != CFG_GLOBAL)
986 continue;
987 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
988 /* prepare error message just in case */
989 snprintf(trash, sizeof(trash),
990 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200991 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
992 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200993 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200994 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200995 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200996 else if (rc > 0) {
997 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200998 err_code |= ERR_WARN;
999 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001000 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001001 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001002 }
1003 }
1004 }
1005
Willy Tarreaubaaee002006-06-26 02:48:02 +02001006 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001009
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 out:
1011 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012}
1013
Willy Tarreau97cb7802010-01-03 20:23:58 +01001014/* Perform the most basic initialization of a proxy :
1015 * memset(), list_init(*), reset_timeouts(*).
1016 */
1017static void init_new_proxy(struct proxy *p)
1018{
1019 memset(p, 0, sizeof(struct proxy));
1020 LIST_INIT(&p->pendconns);
1021 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001022 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001023 LIST_INIT(&p->block_cond);
1024 LIST_INIT(&p->redirect_rules);
1025 LIST_INIT(&p->mon_fail_cond);
1026 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001027 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001028 LIST_INIT(&p->sticking_rules);
1029 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001030 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001031 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001032 LIST_INIT(&p->req_add);
1033 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001034
1035 /* Timeouts are defined as -1 */
1036 proxy_reset_timeouts(p);
1037}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001039void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001041 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 defproxy.mode = PR_MODE_TCP;
1043 defproxy.state = PR_STNEW;
1044 defproxy.maxconn = cfg_maxpconn;
1045 defproxy.conn_retries = CONN_RETRIES;
1046 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001047
1048 defproxy.defsrv.inter = DEF_CHKINTR;
1049 defproxy.defsrv.fastinter = 0;
1050 defproxy.defsrv.downinter = 0;
1051 defproxy.defsrv.rise = DEF_RISETIME;
1052 defproxy.defsrv.fall = DEF_FALLTIME;
1053 defproxy.defsrv.check_port = 0;
1054 defproxy.defsrv.maxqueue = 0;
1055 defproxy.defsrv.minconn = 0;
1056 defproxy.defsrv.maxconn = 0;
1057 defproxy.defsrv.slowstart = 0;
1058 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1059 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1060 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061}
1062
Willy Tarreauade5ec42010-01-28 19:33:49 +01001063
1064static int create_cond_regex_rule(const char *file, int line,
1065 struct proxy *px, int dir, int action, int flags,
1066 const char *cmd, const char *reg, const char *repl,
1067 const char **cond_start)
1068{
1069 regex_t *preg = NULL;
1070 const char *err;
1071 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001072 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001073
1074 if (px == &defproxy) {
1075 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto err;
1078 }
1079
1080 if (*reg == 0) {
1081 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto err;
1084 }
1085
1086 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1087 err_code |= ERR_WARN;
1088
Willy Tarreau5321c422010-01-28 20:35:13 +01001089 if (cond_start &&
1090 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1091 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1092 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1093 file, line, cmd);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto err;
1096 }
1097 }
1098 else if (cond_start && **cond_start) {
1099 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1100 file, line, cmd, *cond_start);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto err;
1103 }
1104
1105 if (dir == ACL_DIR_REQ)
1106 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001107 else
1108 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001109
Willy Tarreauade5ec42010-01-28 19:33:49 +01001110 preg = calloc(1, sizeof(regex_t));
1111 if (!preg) {
1112 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1113 err_code = ERR_ALERT | ERR_FATAL;
1114 goto err;
1115 }
1116
1117 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1118 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1119 err_code = ERR_ALERT | ERR_FATAL;
1120 goto err;
1121 }
1122
1123 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001124 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001125 if (repl && err) {
1126 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1127 file, line, cmd, *err);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto err;
1130 }
1131
1132 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1133 err_code |= ERR_WARN;
1134
1135 return err_code;
1136 err:
1137 free(preg);
1138 return err_code;
1139}
1140
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001142 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001143 * Returns the error code, 0 if OK, or any combination of :
1144 * - ERR_ABORT: must abort ASAP
1145 * - ERR_FATAL: we can continue parsing but not start the service
1146 * - ERR_WARN: a warning has been emitted
1147 * - ERR_ALERT: an alert has been emitted
1148 * Only the two first ones can stop processing, the two others are just
1149 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001151int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152{
1153 static struct proxy *curproxy = NULL;
1154 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001155 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001156 int rc;
1157 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001158 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001159 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160
Willy Tarreau977b8e42006-12-29 14:19:17 +01001161 if (!strcmp(args[0], "listen"))
1162 rc = PR_CAP_LISTEN;
1163 else if (!strcmp(args[0], "frontend"))
1164 rc = PR_CAP_FE | PR_CAP_RS;
1165 else if (!strcmp(args[0], "backend"))
1166 rc = PR_CAP_BE | PR_CAP_RS;
1167 else if (!strcmp(args[0], "ruleset"))
1168 rc = PR_CAP_RS;
1169 else
1170 rc = PR_CAP_NONE;
1171
1172 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 if (!*args[1]) {
1174 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1175 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1176 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001177 err_code |= ERR_ALERT | ERR_ABORT;
1178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001180
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001181 err = invalid_char(args[1]);
1182 if (err) {
1183 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1184 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001185 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001186 }
1187
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001188 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1189 /*
1190 * If there are two proxies with the same name only following
1191 * combinations are allowed:
1192 *
1193 * listen backend frontend ruleset
1194 * listen - - - -
1195 * backend - - OK -
1196 * frontend - OK - -
1197 * ruleset - - - -
1198 */
1199
1200 if (!strcmp(curproxy->id, args[1]) &&
1201 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1202 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001203 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1204 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1205 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001206 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001207 }
1208 }
1209
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1211 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001212 err_code |= ERR_ALERT | ERR_ABORT;
1213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001215
Willy Tarreau97cb7802010-01-03 20:23:58 +01001216 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 curproxy->next = proxy;
1218 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001219 curproxy->conf.file = file;
1220 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001221 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001223 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224
1225 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001226 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001227 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001228 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001229 err_code |= ERR_FATAL;
1230 goto out;
1231 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001232 new = curproxy->listen;
1233 while (new != last) {
1234 new->conf.file = file;
1235 new->conf.line = linenum;
1236 new = new->next;
1237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001238 global.maxsock++;
1239 }
1240
1241 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001242 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001243 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001244
Willy Tarreaubaaee002006-06-26 02:48:02 +02001245 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001247 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001248 curproxy->no_options = defproxy.no_options;
1249 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001250 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001251 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001252 curproxy->except_net = defproxy.except_net;
1253 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001254 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001255 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001257 if (defproxy.fwdfor_hdr_len) {
1258 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1259 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1260 }
1261
Willy Tarreaub86db342009-11-30 11:50:16 +01001262 if (defproxy.orgto_hdr_len) {
1263 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1264 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1265 }
1266
Willy Tarreau977b8e42006-12-29 14:19:17 +01001267 if (curproxy->cap & PR_CAP_FE) {
1268 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001269 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001270 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001271
1272 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001273 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1274 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001275
1276 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001278
Willy Tarreau977b8e42006-12-29 14:19:17 +01001279 if (curproxy->cap & PR_CAP_BE) {
1280 curproxy->fullconn = defproxy.fullconn;
1281 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001283 if (defproxy.check_req) {
1284 curproxy->check_req = calloc(1, defproxy.check_len);
1285 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1286 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001287 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288
Willy Tarreau977b8e42006-12-29 14:19:17 +01001289 if (defproxy.cookie_name)
1290 curproxy->cookie_name = strdup(defproxy.cookie_name);
1291 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001292 if (defproxy.cookie_domain)
1293 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001294
Willy Tarreau31936852010-10-06 16:59:56 +02001295 if (defproxy.cookie_maxidle)
1296 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1297
1298 if (defproxy.cookie_maxlife)
1299 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1300
Emeric Brun647caf12009-06-30 17:57:00 +02001301 if (defproxy.rdp_cookie_name)
1302 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1303 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1304
Willy Tarreau01732802007-11-01 22:48:15 +01001305 if (defproxy.url_param_name)
1306 curproxy->url_param_name = strdup(defproxy.url_param_name);
1307 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001308
Benoitaffb4812009-03-25 13:02:10 +01001309 if (defproxy.hh_name)
1310 curproxy->hh_name = strdup(defproxy.hh_name);
1311 curproxy->hh_len = defproxy.hh_len;
1312 curproxy->hh_match_domain = defproxy.hh_match_domain;
1313
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001314 if (defproxy.iface_name)
1315 curproxy->iface_name = strdup(defproxy.iface_name);
1316 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001319 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001320 if (defproxy.capture_name)
1321 curproxy->capture_name = strdup(defproxy.capture_name);
1322 curproxy->capture_namelen = defproxy.capture_namelen;
1323 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001324 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325
Willy Tarreau977b8e42006-12-29 14:19:17 +01001326 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001327 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001328 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001329 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001330 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001331 curproxy->uri_auth = defproxy.uri_auth;
1332 curproxy->mon_net = defproxy.mon_net;
1333 curproxy->mon_mask = defproxy.mon_mask;
1334 if (defproxy.monitor_uri)
1335 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1336 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001337 if (defproxy.defbe.name)
1338 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001339 }
1340
1341 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001342 curproxy->timeout.connect = defproxy.timeout.connect;
1343 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001344 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001345 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001346 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001347 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001348 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001349 curproxy->source_addr = defproxy.source_addr;
1350 }
1351
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 curproxy->mode = defproxy.mode;
1353 curproxy->logfac1 = defproxy.logfac1;
1354 curproxy->logsrv1 = defproxy.logsrv1;
1355 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001356 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 curproxy->logfac2 = defproxy.logfac2;
1358 curproxy->logsrv2 = defproxy.logsrv2;
1359 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001360 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001362 curproxy->conf.used_listener_id = EB_ROOT;
1363 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001364
Willy Tarreau93893792009-07-23 13:19:11 +02001365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 }
1367 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1368 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001369 /* FIXME-20070101: we should do this too at the end of the
1370 * config parsing to free all default values.
1371 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001372 free(defproxy.check_req);
1373 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001374 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001375 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001376 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001377 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001378 free(defproxy.capture_name);
1379 free(defproxy.monitor_uri);
1380 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001381 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001382 free(defproxy.fwdfor_hdr_name);
1383 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001384 free(defproxy.orgto_hdr_name);
1385 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001386
Willy Tarreaua534fea2008-08-03 12:19:50 +02001387 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001388 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001389
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 /* we cannot free uri_auth because it might already be used */
1391 init_default_instance();
1392 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001393 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 }
1396 else if (curproxy == NULL) {
1397 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
1401
Willy Tarreau977b8e42006-12-29 14:19:17 +01001402
1403 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001405 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001406 int cur_arg;
1407
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 if (curproxy == &defproxy) {
1409 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001413 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001414 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415
Emeric Bruned760922010-10-22 17:59:25 +02001416 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001417 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001422
1423 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001424
1425 /* NOTE: the following line might create several listeners if there
1426 * are comma-separated IPs or port ranges. So all further processing
1427 * will have to be applied to all listeners created after last_listen.
1428 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001429 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001433
Willy Tarreau90a570f2009-10-04 20:54:54 +02001434 new_listen = curproxy->listen;
1435 while (new_listen != last_listen) {
1436 new_listen->conf.file = file;
1437 new_listen->conf.line = linenum;
1438 new_listen = new_listen->next;
1439 }
1440
Emeric Bruned760922010-10-22 17:59:25 +02001441 /* Set default global rights and owner for unix bind */
1442 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1443 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1444 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001445 cur_arg = 2;
1446 while (*(args[cur_arg])) {
1447 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1448#ifdef SO_BINDTODEVICE
1449 struct listener *l;
1450
Emeric Bruned760922010-10-22 17:59:25 +02001451 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1452 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1453 file, linenum, args[0], args[cur_arg]);
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
1456 }
1457
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001458 if (!*args[cur_arg + 1]) {
1459 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001463 }
1464
1465 for (l = curproxy->listen; l != last_listen; l = l->next)
1466 l->interface = strdup(args[cur_arg + 1]);
1467
1468 global.last_checks |= LSTCHK_NETADM;
1469
1470 cur_arg += 2;
1471 continue;
1472#else
1473 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1474 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001477#endif
1478 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001479 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1480#ifdef TCP_MAXSEG
1481 struct listener *l;
1482 int mss;
1483
Emeric Bruned760922010-10-22 17:59:25 +02001484 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1485 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1486 file, linenum, args[0], args[cur_arg]);
1487 err_code |= ERR_ALERT | ERR_FATAL;
1488 goto out;
1489 }
1490
Willy Tarreaube1b9182009-06-14 18:48:19 +02001491 if (!*args[cur_arg + 1]) {
1492 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1493 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001494 err_code |= ERR_ALERT | ERR_FATAL;
1495 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001496 }
1497
1498 mss = str2uic(args[cur_arg + 1]);
1499 if (mss < 1 || mss > 65535) {
1500 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1501 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001502 err_code |= ERR_ALERT | ERR_FATAL;
1503 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001504 }
1505
1506 for (l = curproxy->listen; l != last_listen; l = l->next)
1507 l->maxseg = mss;
1508
1509 cur_arg += 2;
1510 continue;
1511#else
1512 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1513 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001514 err_code |= ERR_ALERT | ERR_FATAL;
1515 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001516#endif
1517 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001518
1519 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1520#ifdef TCP_DEFER_ACCEPT
1521 struct listener *l;
1522
1523 for (l = curproxy->listen; l != last_listen; l = l->next)
1524 l->options |= LI_O_DEF_ACCEPT;
1525
1526 cur_arg ++;
1527 continue;
1528#else
1529 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1530 file, linenum, args[0], args[cur_arg]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533#endif
1534 }
1535
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001536 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001537#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001538 struct listener *l;
1539
Emeric Bruned760922010-10-22 17:59:25 +02001540 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1541 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1542 file, linenum, args[0], args[cur_arg]);
1543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
1546
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001547 for (l = curproxy->listen; l != last_listen; l = l->next)
1548 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001549
1550 cur_arg ++;
1551 continue;
1552#else
1553 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1554 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001557#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001558 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001559
Willy Tarreau8a956912010-10-15 14:27:08 +02001560 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1561 struct listener *l;
1562
1563 for (l = curproxy->listen; l != last_listen; l = l->next)
1564 l->options |= LI_O_ACC_PROXY;
1565
1566 cur_arg ++;
1567 continue;
1568 }
1569
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001570 if (!strcmp(args[cur_arg], "name")) {
1571 struct listener *l;
1572
1573 for (l = curproxy->listen; l != last_listen; l = l->next)
1574 l->name = strdup(args[cur_arg + 1]);
1575
1576 cur_arg += 2;
1577 continue;
1578 }
1579
1580 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001581 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001582 struct listener *l;
1583
1584 if (curproxy->listen->next != last_listen) {
1585 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1586 file, linenum, args[cur_arg]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
1591 if (!*args[cur_arg + 1]) {
1592 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1593 file, linenum, args[cur_arg]);
1594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
1596 }
1597
1598 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001599 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001600
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001601 if (curproxy->listen->luid <= 0) {
1602 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001603 file, linenum);
1604 err_code |= ERR_ALERT | ERR_FATAL;
1605 goto out;
1606 }
1607
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001608 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1609 if (node) {
1610 l = container_of(node, struct listener, conf.id);
1611 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1612 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1613 err_code |= ERR_ALERT | ERR_FATAL;
1614 goto out;
1615 }
1616 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1617
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001618 cur_arg += 2;
1619 continue;
1620 }
1621
Emeric Bruned760922010-10-22 17:59:25 +02001622 if (!strcmp(args[cur_arg], "mode")) {
1623
1624 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1625 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1626 file, linenum, args[0], args[cur_arg]);
1627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
1629 }
1630
1631 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1632
1633 cur_arg += 2;
1634 continue;
1635 }
1636
1637 if (!strcmp(args[cur_arg], "uid")) {
1638
1639 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1640 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1641 file, linenum, args[0], args[cur_arg]);
1642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
1644 }
1645
1646 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1647 cur_arg += 2;
1648 continue;
1649 }
1650
1651 if (!strcmp(args[cur_arg], "gid")) {
1652
1653 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1654 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1655 file, linenum, args[0], args[cur_arg]);
1656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
1658 }
1659
1660 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1661 cur_arg += 2;
1662 continue;
1663 }
1664
1665 if (!strcmp(args[cur_arg], "user")) {
1666 struct passwd *user;
1667
1668 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1669 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1670 file, linenum, args[0], args[cur_arg]);
1671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
1673 }
1674 user = getpwnam(args[cur_arg + 1]);
1675 if (!user) {
1676 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1677 file, linenum, args[0], args[cur_arg + 1 ]);
1678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
1680 }
1681
1682 curproxy->listen->perm.ux.uid = user->pw_uid;
1683 cur_arg += 2;
1684 continue;
1685 }
1686
1687 if (!strcmp(args[cur_arg], "group")) {
1688 struct group *group;
1689
1690 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1691 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1692 file, linenum, args[0], args[cur_arg]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696 group = getgrnam(args[cur_arg + 1]);
1697 if (!group) {
1698 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1699 file, linenum, args[0], args[cur_arg + 1 ]);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703
1704 curproxy->listen->perm.ux.gid = group->gr_gid;
1705 cur_arg += 2;
1706 continue;
1707 }
1708
Willy Tarreau8a956912010-10-15 14:27:08 +02001709 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 }
1717 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1718 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1719 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1720 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001724 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001726
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 /* flush useless bits */
1728 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001731 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001732 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001734
Willy Tarreau1c47f852006-07-09 08:22:27 +02001735 if (!*args[1]) {
1736 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001740 }
1741
Willy Tarreaua534fea2008-08-03 12:19:50 +02001742 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001743 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001744 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001745 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001746 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1747
Willy Tarreau93893792009-07-23 13:19:11 +02001748 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001750 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1751 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1752 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1753 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1754 else {
1755 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 }
1759 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001760 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001761 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001762
1763 if (curproxy == &defproxy) {
1764 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1765 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001768 }
1769
1770 if (!*args[1]) {
1771 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001775 }
1776
1777 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001778 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001779
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001780 if (curproxy->uuid <= 0) {
1781 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001782 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001785 }
1786
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001787 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1788 if (node) {
1789 struct proxy *target = container_of(node, struct proxy, conf.id);
1790 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1791 file, linenum, proxy_type_str(curproxy), curproxy->id,
1792 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001797 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001798 else if (!strcmp(args[0], "description")) {
1799 int i, len=0;
1800 char *d;
1801
Cyril Bonté99ed3272010-01-24 23:29:44 +01001802 if (curproxy == &defproxy) {
1803 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1804 file, linenum, args[0]);
1805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001809 if (!*args[1]) {
1810 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1811 file, linenum, args[0]);
1812 return -1;
1813 }
1814
1815 for(i=1; *args[i]; i++)
1816 len += strlen(args[i])+1;
1817
1818 d = (char *)calloc(1, len);
1819 curproxy->desc = d;
1820
1821 d += sprintf(d, "%s", args[1]);
1822 for(i=2; *args[i]; i++)
1823 d += sprintf(d, " %s", args[i]);
1824
1825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001826 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1827 curproxy->state = PR_STSTOPPED;
1828 }
1829 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1830 curproxy->state = PR_STNEW;
1831 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001832 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1833 int cur_arg = 1;
1834 unsigned int set = 0;
1835
1836 while (*args[cur_arg]) {
1837 int u;
1838 if (strcmp(args[cur_arg], "all") == 0) {
1839 set = 0;
1840 break;
1841 }
1842 else if (strcmp(args[cur_arg], "odd") == 0) {
1843 set |= 0x55555555;
1844 }
1845 else if (strcmp(args[cur_arg], "even") == 0) {
1846 set |= 0xAAAAAAAA;
1847 }
1848 else {
1849 u = str2uic(args[cur_arg]);
1850 if (u < 1 || u > 32) {
1851 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1852 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001855 }
1856 if (u > global.nbproc) {
1857 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1858 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001859 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001860 }
1861 set |= 1 << (u - 1);
1862 }
1863 cur_arg++;
1864 }
1865 curproxy->bind_proc = set;
1866 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001867 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001868 if (curproxy == &defproxy) {
1869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001872 }
1873
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001874 err = invalid_char(args[1]);
1875 if (err) {
1876 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1877 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001878 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001879 }
1880
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001881 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1882 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1883 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001886 }
1887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1889 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890
Willy Tarreau977b8e42006-12-29 14:19:17 +01001891 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001893
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 if (*(args[1]) == 0) {
1895 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001900
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001901 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001902 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001903 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001904 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001905 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 curproxy->cookie_name = strdup(args[1]);
1907 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001908
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 cur_arg = 2;
1910 while (*(args[cur_arg])) {
1911 if (!strcmp(args[cur_arg], "rewrite")) {
1912 curproxy->options |= PR_O_COOK_RW;
1913 }
1914 else if (!strcmp(args[cur_arg], "indirect")) {
1915 curproxy->options |= PR_O_COOK_IND;
1916 }
1917 else if (!strcmp(args[cur_arg], "insert")) {
1918 curproxy->options |= PR_O_COOK_INS;
1919 }
1920 else if (!strcmp(args[cur_arg], "nocache")) {
1921 curproxy->options |= PR_O_COOK_NOC;
1922 }
1923 else if (!strcmp(args[cur_arg], "postonly")) {
1924 curproxy->options |= PR_O_COOK_POST;
1925 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001926 else if (!strcmp(args[cur_arg], "preserve")) {
1927 curproxy->options2 |= PR_O2_COOK_PSV;
1928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 else if (!strcmp(args[cur_arg], "prefix")) {
1930 curproxy->options |= PR_O_COOK_PFX;
1931 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001932 else if (!strcmp(args[cur_arg], "domain")) {
1933 if (!*args[cur_arg + 1]) {
1934 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1935 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001938 }
1939
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001940 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001941 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001942 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1943 " dots nor does not start with a dot."
1944 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001945 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001946 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001947 }
1948
1949 err = invalid_domainchar(args[cur_arg + 1]);
1950 if (err) {
1951 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1952 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001955 }
1956
Willy Tarreau68a897b2009-12-03 23:28:34 +01001957 if (!curproxy->cookie_domain) {
1958 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1959 } else {
1960 /* one domain was already specified, add another one by
1961 * building the string which will be returned along with
1962 * the cookie.
1963 */
1964 char *new_ptr;
1965 int new_len = strlen(curproxy->cookie_domain) +
1966 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1967 new_ptr = malloc(new_len);
1968 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1969 free(curproxy->cookie_domain);
1970 curproxy->cookie_domain = new_ptr;
1971 }
Willy Tarreau31936852010-10-06 16:59:56 +02001972 cur_arg++;
1973 }
1974 else if (!strcmp(args[cur_arg], "maxidle")) {
1975 unsigned int maxidle;
1976 const char *res;
1977
1978 if (!*args[cur_arg + 1]) {
1979 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
1980 file, linenum, args[cur_arg]);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983 }
1984
1985 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
1986 if (res) {
1987 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
1988 file, linenum, *res, args[cur_arg]);
1989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
1991 }
1992 curproxy->cookie_maxidle = maxidle;
1993 cur_arg++;
1994 }
1995 else if (!strcmp(args[cur_arg], "maxlife")) {
1996 unsigned int maxlife;
1997 const char *res;
1998
1999 if (!*args[cur_arg + 1]) {
2000 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2001 file, linenum, args[cur_arg]);
2002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
2004 }
2005
2006 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2007 if (res) {
2008 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2009 file, linenum, *res, args[cur_arg]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
2013 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002014 cur_arg++;
2015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002016 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002017 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 +02002018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 }
2022 cur_arg++;
2023 }
2024 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2025 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2026 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 }
2029
2030 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2031 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2032 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002035
2036 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2037 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2038 file, linenum);
2039 err_code |= ERR_ALERT | ERR_FATAL;
2040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002042 else if (!strcmp(args[0], "persist")) { /* persist */
2043 if (*(args[1]) == 0) {
2044 Alert("parsing [%s:%d] : missing persist method.\n",
2045 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002048 }
2049
2050 if (!strncmp(args[1], "rdp-cookie", 10)) {
2051 curproxy->options2 |= PR_O2_RDPC_PRST;
2052
Emeric Brunb982a3d2010-01-04 15:45:53 +01002053 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002054 const char *beg, *end;
2055
2056 beg = args[1] + 11;
2057 end = strchr(beg, ')');
2058
2059 if (!end || end == beg) {
2060 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2061 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002062 err_code |= ERR_ALERT | ERR_FATAL;
2063 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002064 }
2065
2066 free(curproxy->rdp_cookie_name);
2067 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2068 curproxy->rdp_cookie_len = end-beg;
2069 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002070 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002071 free(curproxy->rdp_cookie_name);
2072 curproxy->rdp_cookie_name = strdup("msts");
2073 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2074 }
2075 else { /* syntax */
2076 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2077 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002080 }
2081 }
2082 else {
2083 Alert("parsing [%s:%d] : unknown persist method.\n",
2084 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002087 }
2088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002090 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002092 if (curproxy == &defproxy) {
2093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
2097
Willy Tarreau977b8e42006-12-29 14:19:17 +01002098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002099 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002100
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002102 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
2107 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002108 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 curproxy->appsession_name = strdup(args[1]);
2110 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2111 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002112 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2113 if (err) {
2114 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2115 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002116 err_code |= ERR_ALERT | ERR_FATAL;
2117 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002118 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002119 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002120
Willy Tarreau51041c72007-09-09 21:56:53 +02002121 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2122 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_ABORT;
2124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002126
2127 cur_arg = 6;
2128 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002129 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2130 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002131 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002132 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002133 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002134 } else if (!strcmp(args[cur_arg], "prefix")) {
2135 curproxy->options2 |= PR_O2_AS_PFX;
2136 } else if (!strcmp(args[cur_arg], "mode")) {
2137 if (!*args[cur_arg + 1]) {
2138 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2139 file, linenum, args[0], args[cur_arg]);
2140 err_code |= ERR_ALERT | ERR_FATAL;
2141 goto out;
2142 }
2143
2144 cur_arg++;
2145 if (!strcmp(args[cur_arg], "query-string")) {
2146 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2147 curproxy->options2 |= PR_O2_AS_M_QS;
2148 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2149 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2150 curproxy->options2 |= PR_O2_AS_M_PP;
2151 } else {
2152 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2153 err_code |= ERR_ALERT | ERR_FATAL;
2154 goto out;
2155 }
2156 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002157 cur_arg++;
2158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 } /* Url App Session */
2160 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002161 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002163
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002165 if (curproxy == &defproxy) {
2166 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 if (*(args[4]) == 0) {
2172 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2173 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002177 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 curproxy->capture_name = strdup(args[2]);
2179 curproxy->capture_namelen = strlen(curproxy->capture_name);
2180 curproxy->capture_len = atol(args[4]);
2181 if (curproxy->capture_len >= CAPTURE_LEN) {
2182 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2183 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 curproxy->capture_len = CAPTURE_LEN - 1;
2186 }
2187 curproxy->to_log |= LW_COOKIE;
2188 }
2189 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2190 struct cap_hdr *hdr;
2191
2192 if (curproxy == &defproxy) {
2193 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 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 }
2197
2198 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2199 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2200 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
2204
2205 hdr = calloc(sizeof(struct cap_hdr), 1);
2206 hdr->next = curproxy->req_cap;
2207 hdr->name = strdup(args[3]);
2208 hdr->namelen = strlen(args[3]);
2209 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002210 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 hdr->index = curproxy->nb_req_cap++;
2212 curproxy->req_cap = hdr;
2213 curproxy->to_log |= LW_REQHDR;
2214 }
2215 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2216 struct cap_hdr *hdr;
2217
2218 if (curproxy == &defproxy) {
2219 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 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 }
2223
2224 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2225 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2226 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 }
2230 hdr = calloc(sizeof(struct cap_hdr), 1);
2231 hdr->next = curproxy->rsp_cap;
2232 hdr->name = strdup(args[3]);
2233 hdr->namelen = strlen(args[3]);
2234 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002235 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 hdr->index = curproxy->nb_rsp_cap++;
2237 curproxy->rsp_cap = hdr;
2238 curproxy->to_log |= LW_RSPHDR;
2239 }
2240 else {
2241 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
2246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002248 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 if (*(args[1]) == 0) {
2252 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
2257 curproxy->conn_retries = atol(args[1]);
2258 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002259 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2260 struct req_acl_rule *req_acl;
2261
2262 if (curproxy == &defproxy) {
2263 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
2266 }
2267
2268
2269 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2270 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2271 file, linenum, args[0]);
2272 err_code |= ERR_WARN;
2273 }
2274
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002275 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002276
2277 if (!req_acl) {
2278 err_code |= ERR_ALERT | ERR_ABORT;
2279 goto out;
2280 }
2281
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002282 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002283 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2284 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002285 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002286 if (curproxy == &defproxy) {
2287 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002290 }
2291
Willy Tarreauef6494c2010-01-28 17:12:36 +01002292 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002293 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2294 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002297 }
2298
Willy Tarreauef6494c2010-01-28 17:12:36 +01002299 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002300 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2301 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002304 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002305
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002306 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002307 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002308 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002309 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002310 struct redirect_rule *rule;
2311 int cur_arg;
2312 int type = REDIRECT_TYPE_NONE;
2313 int code = 302;
2314 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002315 char *cookie = NULL;
2316 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002317 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002318
Cyril Bonté99ed3272010-01-24 23:29:44 +01002319 if (curproxy == &defproxy) {
2320 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002325 cur_arg = 1;
2326 while (*(args[cur_arg])) {
2327 if (!strcmp(args[cur_arg], "location")) {
2328 if (!*args[cur_arg + 1]) {
2329 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2330 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002333 }
2334
2335 type = REDIRECT_TYPE_LOCATION;
2336 cur_arg++;
2337 destination = args[cur_arg];
2338 }
2339 else if (!strcmp(args[cur_arg], "prefix")) {
2340 if (!*args[cur_arg + 1]) {
2341 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2342 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002345 }
2346
2347 type = REDIRECT_TYPE_PREFIX;
2348 cur_arg++;
2349 destination = args[cur_arg];
2350 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002351 else if (!strcmp(args[cur_arg], "set-cookie")) {
2352 if (!*args[cur_arg + 1]) {
2353 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2354 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002357 }
2358
2359 cur_arg++;
2360 cookie = args[cur_arg];
2361 cookie_set = 1;
2362 }
2363 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2364 if (!*args[cur_arg + 1]) {
2365 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2366 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002369 }
2370
2371 cur_arg++;
2372 cookie = args[cur_arg];
2373 cookie_set = 0;
2374 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002375 else if (!strcmp(args[cur_arg],"code")) {
2376 if (!*args[cur_arg + 1]) {
2377 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2378 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002381 }
2382 cur_arg++;
2383 code = atol(args[cur_arg]);
2384 if (code < 301 || code > 303) {
2385 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2386 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002389 }
2390 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002391 else if (!strcmp(args[cur_arg],"drop-query")) {
2392 flags |= REDIRECT_FLAG_DROP_QS;
2393 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002394 else if (!strcmp(args[cur_arg],"append-slash")) {
2395 flags |= REDIRECT_FLAG_APPEND_SLASH;
2396 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002397 else if (strcmp(args[cur_arg], "if") == 0 ||
2398 strcmp(args[cur_arg], "unless") == 0) {
2399 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2400 if (!cond) {
2401 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2402 file, linenum, args[0]);
2403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
2405 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002406 break;
2407 }
2408 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002409 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002410 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002413 }
2414 cur_arg++;
2415 }
2416
2417 if (type == REDIRECT_TYPE_NONE) {
2418 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002422 }
2423
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002424 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2425 rule->cond = cond;
2426 rule->rdr_str = strdup(destination);
2427 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002428 if (cookie) {
2429 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002430 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002431 */
2432 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002433 if (cookie_set) {
2434 rule->cookie_str = malloc(rule->cookie_len + 10);
2435 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2436 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2437 rule->cookie_len += 9;
2438 } else {
2439 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002440 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002441 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2442 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002443 }
2444 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002445 rule->type = type;
2446 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002447 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002448 LIST_INIT(&rule->list);
2449 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002450 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002451 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002452 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002453 struct switching_rule *rule;
2454
Willy Tarreaub099aca2008-10-12 17:26:37 +02002455 if (curproxy == &defproxy) {
2456 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002459 }
2460
Willy Tarreau55ea7572007-06-17 19:56:27 +02002461 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002463
2464 if (*(args[1]) == 0) {
2465 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002468 }
2469
Willy Tarreauef6494c2010-01-28 17:12:36 +01002470 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002471 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002475 }
2476
Willy Tarreauef6494c2010-01-28 17:12:36 +01002477 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002478 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002479 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002482 }
2483
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002484 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002485
Willy Tarreau55ea7572007-06-17 19:56:27 +02002486 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2487 rule->cond = cond;
2488 rule->be.name = strdup(args[1]);
2489 LIST_INIT(&rule->list);
2490 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2491 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002492 else if ((!strcmp(args[0], "force-persist")) ||
2493 (!strcmp(args[0], "ignore-persist"))) {
2494 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002495
2496 if (curproxy == &defproxy) {
2497 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
2501
2502 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2503 err_code |= ERR_WARN;
2504
Willy Tarreauef6494c2010-01-28 17:12:36 +01002505 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002506 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2507 file, linenum, args[0]);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511
Willy Tarreauef6494c2010-01-28 17:12:36 +01002512 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002513 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2514 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
2517 }
2518
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002519 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002520
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002521 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002522 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002523 if (!strcmp(args[0], "force-persist")) {
2524 rule->type = PERSIST_TYPE_FORCE;
2525 } else {
2526 rule->type = PERSIST_TYPE_IGNORE;
2527 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002528 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002529 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002530 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002531 else if (!strcmp(args[0], "stick-table")) {
2532 int myidx = 1;
2533
2534 curproxy->table.type = (unsigned int)-1;
2535 while (*args[myidx]) {
2536 const char *err;
2537
2538 if (strcmp(args[myidx], "size") == 0) {
2539 myidx++;
2540 if (!*(args[myidx])) {
2541 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2542 file, linenum, args[myidx-1]);
2543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
2545 }
2546 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2547 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2548 file, linenum, *err, args[myidx-1]);
2549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
2551 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002552 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002553 }
2554 else if (strcmp(args[myidx], "expire") == 0) {
2555 myidx++;
2556 if (!*(args[myidx])) {
2557 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2558 file, linenum, args[myidx-1]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2563 if (err) {
2564 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2565 file, linenum, *err, args[myidx-1]);
2566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
2568 }
2569 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002570 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002571 }
2572 else if (strcmp(args[myidx], "nopurge") == 0) {
2573 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002574 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002575 }
2576 else if (strcmp(args[myidx], "type") == 0) {
2577 myidx++;
2578 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2579 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2580 file, linenum, args[myidx]);
2581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
2583 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002584 /* myidx already points to next arg */
2585 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002586 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002587 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002588 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002589
2590 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002591 nw = args[myidx];
2592 while (*nw) {
2593 /* the "store" keyword supports a comma-separated list */
2594 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002595 sa = NULL; /* store arg */
2596 while (*nw && *nw != ',') {
2597 if (*nw == '(') {
2598 *nw = 0;
2599 sa = ++nw;
2600 while (*nw != ')') {
2601 if (!*nw) {
2602 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2603 file, linenum, args[0], cw);
2604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
2606 }
2607 nw++;
2608 }
2609 *nw = '\0';
2610 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002611 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002612 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002613 if (*nw)
2614 *nw++ = '\0';
2615 type = stktable_get_data_type(cw);
2616 if (type < 0) {
2617 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2618 file, linenum, args[0], cw);
2619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
2621 }
Willy Tarreauac782882010-06-20 10:41:54 +02002622
2623 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2624 switch (err) {
2625 case PE_NONE: break;
2626 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002627 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2628 file, linenum, args[0], cw);
2629 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002630 break;
2631
2632 case PE_ARG_MISSING:
2633 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2634 file, linenum, args[0], cw);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637
2638 case PE_ARG_NOT_USED:
2639 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2640 file, linenum, args[0], cw);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643
2644 default:
2645 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2646 file, linenum, args[0], cw);
2647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002649 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002650 }
2651 myidx++;
2652 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002653 else {
2654 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2655 file, linenum, args[myidx]);
2656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002658 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002659 }
2660
2661 if (!curproxy->table.size) {
2662 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2663 file, linenum);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
2668 if (curproxy->table.type == (unsigned int)-1) {
2669 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2670 file, linenum);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674 }
2675 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002676 struct sticking_rule *rule;
2677 struct pattern_expr *expr;
2678 int myidx = 0;
2679 const char *name = NULL;
2680 int flags;
2681
2682 if (curproxy == &defproxy) {
2683 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2684 err_code |= ERR_ALERT | ERR_FATAL;
2685 goto out;
2686 }
2687
2688 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2689 err_code |= ERR_WARN;
2690 goto out;
2691 }
2692
2693 myidx++;
2694 if ((strcmp(args[myidx], "store") == 0) ||
2695 (strcmp(args[myidx], "store-request") == 0)) {
2696 myidx++;
2697 flags = STK_IS_STORE;
2698 }
2699 else if (strcmp(args[myidx], "store-response") == 0) {
2700 myidx++;
2701 flags = STK_IS_STORE | STK_ON_RSP;
2702 }
2703 else if (strcmp(args[myidx], "match") == 0) {
2704 myidx++;
2705 flags = STK_IS_MATCH;
2706 }
2707 else if (strcmp(args[myidx], "on") == 0) {
2708 myidx++;
2709 flags = STK_IS_MATCH | STK_IS_STORE;
2710 }
2711 else {
2712 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716
2717 if (*(args[myidx]) == 0) {
2718 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722
2723 expr = pattern_parse_expr(args, &myidx);
2724 if (!expr) {
2725 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
2728 }
2729
2730 if (flags & STK_ON_RSP) {
2731 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2732 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2733 file, linenum, args[0], expr->fetch->kw);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737 } else {
2738 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2739 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2740 file, linenum, args[0], expr->fetch->kw);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744 }
2745
2746 if (strcmp(args[myidx], "table") == 0) {
2747 myidx++;
2748 name = args[myidx++];
2749 }
2750
Willy Tarreauef6494c2010-01-28 17:12:36 +01002751 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2752 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002753 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2754 file, linenum, args[0]);
2755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002758 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002759 else if (*(args[myidx])) {
2760 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2761 file, linenum, args[0], args[myidx]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002766 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2767
Emeric Brunb982a3d2010-01-04 15:45:53 +01002768 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2769 rule->cond = cond;
2770 rule->expr = expr;
2771 rule->flags = flags;
2772 rule->table.name = name ? strdup(name) : NULL;
2773 LIST_INIT(&rule->list);
2774 if (flags & STK_ON_RSP)
2775 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2776 else
2777 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002780 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002782
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2784 curproxy->uri_auth = NULL; /* we must detach from the default config */
2785
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002786 if (!*args[1]) {
2787 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002788 } else if (!strcmp(args[1], "admin")) {
2789 struct stats_admin_rule *rule;
2790
2791 if (curproxy == &defproxy) {
2792 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
2795 }
2796
2797 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2798 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2799 err_code |= ERR_ALERT | ERR_ABORT;
2800 goto out;
2801 }
2802
2803 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2804 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2805 file, linenum, args[0], args[1]);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
2808 }
2809 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2810 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2811 file, linenum, args[0], args[1]);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814 }
2815
2816 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2817
2818 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2819 rule->cond = cond;
2820 LIST_INIT(&rule->list);
2821 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 } else if (!strcmp(args[1], "uri")) {
2823 if (*(args[2]) == 0) {
2824 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2828 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_ABORT;
2830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 }
2832 } else if (!strcmp(args[1], "realm")) {
2833 if (*(args[2]) == 0) {
2834 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2838 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_ABORT;
2840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002842 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002843 unsigned interval;
2844
2845 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2846 if (err) {
2847 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2848 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002851 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2852 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_ABORT;
2854 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002855 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002856 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2857 struct req_acl_rule *req_acl;
2858
2859 if (curproxy == &defproxy) {
2860 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864
2865 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2866 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2867 err_code |= ERR_ALERT | ERR_ABORT;
2868 goto out;
2869 }
2870
2871 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2872 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2873 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2874 file, linenum, args[0]);
2875 err_code |= ERR_WARN;
2876 }
2877
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002878 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002879
2880 if (!req_acl) {
2881 err_code |= ERR_ALERT | ERR_ABORT;
2882 goto out;
2883 }
2884
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002885 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002886 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2887
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 } else if (!strcmp(args[1], "auth")) {
2889 if (*(args[2]) == 0) {
2890 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2894 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_ABORT;
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
2898 } else if (!strcmp(args[1], "scope")) {
2899 if (*(args[2]) == 0) {
2900 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2904 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_ABORT;
2906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 }
2908 } else if (!strcmp(args[1], "enable")) {
2909 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2910 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_ABORT;
2912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002914 } else if (!strcmp(args[1], "hide-version")) {
2915 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2916 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_ABORT;
2918 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002919 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002920 } else if (!strcmp(args[1], "show-legends")) {
2921 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2922 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2923 err_code |= ERR_ALERT | ERR_ABORT;
2924 goto out;
2925 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002926 } else if (!strcmp(args[1], "show-node")) {
2927
2928 if (*args[2]) {
2929 int i;
2930 char c;
2931
2932 for (i=0; args[2][i]; i++) {
2933 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002934 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2935 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002936 break;
2937 }
2938
2939 if (!i || args[2][i]) {
2940 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2941 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2942 file, linenum, args[0], args[1]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946 }
2947
2948 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2949 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2950 err_code |= ERR_ALERT | ERR_ABORT;
2951 goto out;
2952 }
2953 } else if (!strcmp(args[1], "show-desc")) {
2954 char *desc = NULL;
2955
2956 if (*args[2]) {
2957 int i, len=0;
2958 char *d;
2959
2960 for(i=2; *args[i]; i++)
2961 len += strlen(args[i])+1;
2962
2963 desc = d = (char *)calloc(1, len);
2964
2965 d += sprintf(d, "%s", args[2]);
2966 for(i=3; *args[i]; i++)
2967 d += sprintf(d, " %s", args[i]);
2968 }
2969
2970 if (!*args[2] && !global.desc)
2971 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2972 file, linenum, args[1]);
2973 else {
2974 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2975 free(desc);
2976 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2977 err_code |= ERR_ALERT | ERR_ABORT;
2978 goto out;
2979 }
2980 free(desc);
2981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002983stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02002984 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 +01002985 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 }
2989 }
2990 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002991 int optnum;
2992
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002993 if (*(args[1]) == '\0') {
2994 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2995 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002999
3000 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3001 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02003002 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3003 err_code |= ERR_WARN;
3004 goto out;
3005 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003006
Willy Tarreau3842f002009-06-14 11:39:52 +02003007 curproxy->no_options &= ~cfg_opts[optnum].val;
3008 curproxy->options &= ~cfg_opts[optnum].val;
3009
3010 switch (kwm) {
3011 case KWM_STD:
3012 curproxy->options |= cfg_opts[optnum].val;
3013 break;
3014 case KWM_NO:
3015 curproxy->no_options |= cfg_opts[optnum].val;
3016 break;
3017 case KWM_DEF: /* already cleared */
3018 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003019 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003020
Willy Tarreau93893792009-07-23 13:19:11 +02003021 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003022 }
3023 }
3024
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003025 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3026 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02003027 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3028 err_code |= ERR_WARN;
3029 goto out;
3030 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003031
Willy Tarreau3842f002009-06-14 11:39:52 +02003032 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3033 curproxy->options2 &= ~cfg_opts2[optnum].val;
3034
3035 switch (kwm) {
3036 case KWM_STD:
3037 curproxy->options2 |= cfg_opts2[optnum].val;
3038 break;
3039 case KWM_NO:
3040 curproxy->no_options2 |= cfg_opts2[optnum].val;
3041 break;
3042 case KWM_DEF: /* already cleared */
3043 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003044 }
Willy Tarreau93893792009-07-23 13:19:11 +02003045 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003046 }
3047 }
3048
Willy Tarreau3842f002009-06-14 11:39:52 +02003049 if (kwm != KWM_STD) {
3050 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003051 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003054 }
3055
Emeric Brun3a058f32009-06-30 18:26:00 +02003056 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003058 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003060 if (*(args[2]) != '\0') {
3061 if (!strcmp(args[2], "clf")) {
3062 curproxy->options2 |= PR_O2_CLFLOG;
3063 } else {
3064 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003067 }
3068 }
3069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 else if (!strcmp(args[1], "tcplog"))
3071 /* generate a detailed TCP log */
3072 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 else if (!strcmp(args[1], "tcpka")) {
3074 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003075 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003077
3078 if (curproxy->cap & PR_CAP_FE)
3079 curproxy->options |= PR_O_TCP_CLI_KA;
3080 if (curproxy->cap & PR_CAP_BE)
3081 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
3083 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003084 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_WARN;
3086
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003088 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003089 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003090 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003091 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003092 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003093 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003094 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 if (!*args[2]) { /* no argument */
3096 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3097 curproxy->check_len = strlen(DEF_CHECK_REQ);
3098 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003099 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 curproxy->check_req = (char *)malloc(reqlen);
3101 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003102 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003104 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 if (*args[4])
3106 reqlen += strlen(args[4]);
3107 else
3108 reqlen += strlen("HTTP/1.0");
3109
3110 curproxy->check_req = (char *)malloc(reqlen);
3111 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003112 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003114 }
3115 else if (!strcmp(args[1], "ssl-hello-chk")) {
3116 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003117 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003119
Willy Tarreaua534fea2008-08-03 12:19:50 +02003120 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003121 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003122 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003123 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003124 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003125 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003126 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 }
Willy Tarreau23677902007-05-08 23:50:35 +02003128 else if (!strcmp(args[1], "smtpchk")) {
3129 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003130 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003131 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003132 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003133 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003134 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003135 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003136 curproxy->options |= PR_O_SMTP_CHK;
3137
3138 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3139 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3140 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3141 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3142 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3143 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3144 curproxy->check_req = (char *)malloc(reqlen);
3145 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3146 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3147 } else {
3148 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3149 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3150 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3151 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3152 }
3153 }
3154 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003155 else if (!strcmp(args[1], "mysql-check")) {
3156 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003157 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3158 err_code |= ERR_WARN;
3159
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003160 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003161 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003162 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003163 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003164 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003165 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003166 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003167
3168 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3169 * const char mysql40_client_auth_pkt[] = {
3170 * "\x0e\x00\x00" // packet length
3171 * "\x01" // packet number
3172 * "\x00\x00" // client capabilities
3173 * "\x00\x00\x01" // max packet
3174 * "haproxy\x00" // username (null terminated string)
3175 * "\x00" // filler (always 0x00)
3176 * "\x01\x00\x00" // packet length
3177 * "\x00" // packet number
3178 * "\x01" // COM_QUIT command
3179 * };
3180 */
3181
3182 if (*(args[2])) {
3183 int cur_arg = 2;
3184
3185 while (*(args[cur_arg])) {
3186 if (strcmp(args[cur_arg], "user") == 0) {
3187 char *mysqluser;
3188 int packetlen, reqlen, userlen;
3189
3190 /* suboption header - needs additional argument for it */
3191 if (*(args[cur_arg+1]) == 0) {
3192 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3193 file, linenum, args[0], args[1], args[cur_arg]);
3194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
3196 }
3197 mysqluser = args[cur_arg + 1];
3198 userlen = strlen(mysqluser);
3199 packetlen = userlen + 7;
3200 reqlen = packetlen + 9;
3201
3202 free(curproxy->check_req);
3203 curproxy->check_req = (char *)calloc(1, reqlen);
3204 curproxy->check_len = reqlen;
3205
3206 snprintf(curproxy->check_req, 4, "%c%c%c",
3207 ((unsigned char) packetlen & 0xff),
3208 ((unsigned char) (packetlen >> 8) & 0xff),
3209 ((unsigned char) (packetlen >> 16) & 0xff));
3210
3211 curproxy->check_req[3] = 1;
3212 curproxy->check_req[8] = 1;
3213 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3214 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3215 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3216 cur_arg += 2;
3217 } else {
3218 /* unknown suboption - catchall */
3219 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3220 file, linenum, args[0], args[1]);
3221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
3223 }
3224 } /* end while loop */
3225 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003226 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003227 else if (!strcmp(args[1], "ldap-check")) {
3228 /* use LDAP request to check servers' health */
3229 free(curproxy->check_req);
3230 curproxy->check_req = NULL;
3231 curproxy->options &= ~PR_O_HTTP_CHK;
3232 curproxy->options &= ~PR_O_SMTP_CHK;
3233 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3234 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3235 curproxy->options2 |= PR_O2_LDAP_CHK;
3236
3237 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3238 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3239 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3240 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003241 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003242 int cur_arg;
3243
3244 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3245 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003246 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003247
3248 curproxy->options |= PR_O_FWDFOR;
3249
3250 free(curproxy->fwdfor_hdr_name);
3251 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3252 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3253
3254 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3255 cur_arg = 2;
3256 while (*(args[cur_arg])) {
3257 if (!strcmp(args[cur_arg], "except")) {
3258 /* suboption except - needs additional argument for it */
3259 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3260 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3261 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003264 }
3265 /* flush useless bits */
3266 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003267 cur_arg += 2;
3268 } else if (!strcmp(args[cur_arg], "header")) {
3269 /* suboption header - needs additional argument for it */
3270 if (*(args[cur_arg+1]) == 0) {
3271 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3272 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003275 }
3276 free(curproxy->fwdfor_hdr_name);
3277 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3278 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3279 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003280 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003281 /* unknown suboption - catchall */
3282 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3283 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003286 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003287 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003288 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003289 else if (!strcmp(args[1], "originalto")) {
3290 int cur_arg;
3291
3292 /* insert x-original-to field, but not for the IP address listed as an except.
3293 * set default options (ie: bitfield, header name, etc)
3294 */
3295
3296 curproxy->options |= PR_O_ORGTO;
3297
3298 free(curproxy->orgto_hdr_name);
3299 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3300 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3301
3302 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3303 cur_arg = 2;
3304 while (*(args[cur_arg])) {
3305 if (!strcmp(args[cur_arg], "except")) {
3306 /* suboption except - needs additional argument for it */
3307 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3308 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3309 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003312 }
3313 /* flush useless bits */
3314 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3315 cur_arg += 2;
3316 } else if (!strcmp(args[cur_arg], "header")) {
3317 /* suboption header - needs additional argument for it */
3318 if (*(args[cur_arg+1]) == 0) {
3319 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3320 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003323 }
3324 free(curproxy->orgto_hdr_name);
3325 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3326 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3327 cur_arg += 2;
3328 } else {
3329 /* unknown suboption - catchall */
3330 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3331 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003334 }
3335 } /* end while loop */
3336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 else {
3338 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 }
Willy Tarreau93893792009-07-23 13:19:11 +02003342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003344 else if (!strcmp(args[0], "default_backend")) {
3345 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003347
3348 if (*(args[1]) == 0) {
3349 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003352 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003353 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003354 curproxy->defbe.name = strdup(args[1]);
3355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003357 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003359
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003360 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3361 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 /* enable reconnections to dispatch */
3364 curproxy->options |= PR_O_REDISP;
3365 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003366 else if (!strcmp(args[0], "http-check")) {
3367 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003369
3370 if (strcmp(args[1], "disable-on-404") == 0) {
3371 /* enable a graceful server shutdown on an HTTP 404 response */
3372 curproxy->options |= PR_O_DISABLE404;
3373 }
Willy Tarreauef781042010-01-27 11:53:01 +01003374 else if (strcmp(args[1], "send-state") == 0) {
3375 /* enable emission of the apparent state of a server in HTTP checks */
3376 curproxy->options2 |= PR_O2_CHK_SNDST;
3377 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003378 else if (strcmp(args[1], "expect") == 0) {
3379 const char *ptr_arg;
3380 int cur_arg;
3381
3382 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3383 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
3387
3388 cur_arg = 2;
3389 /* consider exclamation marks, sole or at the beginning of a word */
3390 while (*(ptr_arg = args[cur_arg])) {
3391 while (*ptr_arg == '!') {
3392 curproxy->options2 ^= PR_O2_EXP_INV;
3393 ptr_arg++;
3394 }
3395 if (*ptr_arg)
3396 break;
3397 cur_arg++;
3398 }
3399 /* now ptr_arg points to the beginning of a word past any possible
3400 * exclamation mark, and cur_arg is the argument which holds this word.
3401 */
3402 if (strcmp(ptr_arg, "status") == 0) {
3403 if (!*(args[cur_arg + 1])) {
3404 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3405 file, linenum, args[0], args[1], ptr_arg);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409 curproxy->options2 |= PR_O2_EXP_STS;
3410 curproxy->expect_str = strdup(args[cur_arg + 1]);
3411 }
3412 else if (strcmp(ptr_arg, "string") == 0) {
3413 if (!*(args[cur_arg + 1])) {
3414 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3415 file, linenum, args[0], args[1], ptr_arg);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419 curproxy->options2 |= PR_O2_EXP_STR;
3420 curproxy->expect_str = strdup(args[cur_arg + 1]);
3421 }
3422 else if (strcmp(ptr_arg, "rstatus") == 0) {
3423 if (!*(args[cur_arg + 1])) {
3424 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3425 file, linenum, args[0], args[1], ptr_arg);
3426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
3428 }
3429 curproxy->options2 |= PR_O2_EXP_RSTS;
3430 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3431 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3432 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3433 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437 }
3438 else if (strcmp(ptr_arg, "rstring") == 0) {
3439 if (!*(args[cur_arg + 1])) {
3440 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3441 file, linenum, args[0], args[1], ptr_arg);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445 curproxy->options2 |= PR_O2_EXP_RSTR;
3446 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3447 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3448 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3449 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
3452 }
3453 }
3454 else {
3455 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3456 file, linenum, args[0], args[1], ptr_arg);
3457 err_code |= ERR_ALERT | ERR_FATAL;
3458 goto out;
3459 }
3460 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003461 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003462 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003465 }
3466 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003467 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003468 if (curproxy == &defproxy) {
3469 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003472 }
3473
Willy Tarreaub80c2302007-11-30 20:51:32 +01003474 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003476
3477 if (strcmp(args[1], "fail") == 0) {
3478 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003479 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003480 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3481 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003484 }
3485
Willy Tarreauef6494c2010-01-28 17:12:36 +01003486 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003487 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3488 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003491 }
3492 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3493 }
3494 else {
3495 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003498 }
3499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500#ifdef TPROXY
3501 else if (!strcmp(args[0], "transparent")) {
3502 /* enable transparent proxy connections */
3503 curproxy->options |= PR_O_TRANSP;
3504 }
3505#endif
3506 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003507 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003508 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003509
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 if (*(args[1]) == 0) {
3511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 }
3515 curproxy->maxconn = atol(args[1]);
3516 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003517 else if (!strcmp(args[0], "backlog")) { /* backlog */
3518 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003520
3521 if (*(args[1]) == 0) {
3522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003525 }
3526 curproxy->backlog = atol(args[1]);
3527 }
Willy Tarreau86034312006-12-29 00:10:33 +01003528 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003529 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003531
Willy Tarreau86034312006-12-29 00:10:33 +01003532 if (*(args[1]) == 0) {
3533 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003536 }
3537 curproxy->fullconn = atol(args[1]);
3538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3540 if (*(args[1]) == 0) {
3541 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003545 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3546 if (err) {
3547 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3548 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003551 }
3552 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }
3554 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003555 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003556 if (curproxy == &defproxy) {
3557 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003561 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003563
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 if (strchr(args[1], ':') == NULL) {
3565 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003569 sk = str2sa(args[1]);
3570 if (!sk) {
3571 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
3575 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 }
3577 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003578 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003580
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003581 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003582 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3583 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003588 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3589 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3590 err_code |= ERR_WARN;
3591
3592 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3593 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3594 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3595 }
3596 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3597 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3598 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3599 }
3600 else {
3601 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003606 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003608 char *rport, *raddr;
3609 short realport = 0;
3610 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003612 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003617 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619
3620 if (!*args[2]) {
3621 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003626
3627 err = invalid_char(args[1]);
3628 if (err) {
3629 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3630 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003633 }
3634
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003635 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003636 struct sockaddr_in *sk;
3637
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003638 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3639 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3640 err_code |= ERR_ALERT | ERR_ABORT;
3641 goto out;
3642 }
3643
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003644 /* the servers are linked backwards first */
3645 newsrv->next = curproxy->srv;
3646 curproxy->srv = newsrv;
3647 newsrv->proxy = curproxy;
3648 newsrv->conf.file = file;
3649 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003651 LIST_INIT(&newsrv->pendconns);
3652 do_check = 0;
3653 newsrv->state = SRV_RUNNING; /* early server setup */
3654 newsrv->last_change = now.tv_sec;
3655 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003657 /* several ways to check the port component :
3658 * - IP => port=+0, relative
3659 * - IP: => port=+0, relative
3660 * - IP:N => port=N, absolute
3661 * - IP:+N => port=+N, relative
3662 * - IP:-N => port=-N, relative
3663 */
3664 raddr = strdup(args[2]);
3665 rport = strchr(raddr, ':');
3666 if (rport) {
3667 *rport++ = 0;
3668 realport = atol(rport);
3669 if (!isdigit((unsigned char)*rport))
3670 newsrv->state |= SRV_MAPPORTS;
3671 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003673
Willy Tarreaud5191e72010-02-09 20:50:45 +01003674 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003675 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003676 if (!sk) {
3677 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
3681 newsrv->addr = *sk;
3682 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003683
3684 newsrv->check_port = curproxy->defsrv.check_port;
3685 newsrv->inter = curproxy->defsrv.inter;
3686 newsrv->fastinter = curproxy->defsrv.fastinter;
3687 newsrv->downinter = curproxy->defsrv.downinter;
3688 newsrv->rise = curproxy->defsrv.rise;
3689 newsrv->fall = curproxy->defsrv.fall;
3690 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3691 newsrv->minconn = curproxy->defsrv.minconn;
3692 newsrv->maxconn = curproxy->defsrv.maxconn;
3693 newsrv->slowstart = curproxy->defsrv.slowstart;
3694 newsrv->onerror = curproxy->defsrv.onerror;
3695 newsrv->consecutive_errors_limit
3696 = curproxy->defsrv.consecutive_errors_limit;
3697 newsrv->uweight = newsrv->iweight
3698 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003700 newsrv->curfd = -1; /* no health-check in progress */
3701 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003703 cur_arg = 3;
3704 } else {
3705 newsrv = &curproxy->defsrv;
3706 cur_arg = 1;
3707 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003708
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003710 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003711 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003712
3713 if (!*args[cur_arg + 1]) {
3714 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3715 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003718 }
3719
3720 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003721 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003722
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003723 if (newsrv->puid <= 0) {
3724 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003725 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003728 }
3729
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003730 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3731 if (node) {
3732 struct server *target = container_of(node, struct server, conf.id);
3733 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3734 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
3737 }
3738 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003739 cur_arg += 2;
3740 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003741 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 newsrv->cookie = strdup(args[cur_arg + 1]);
3743 newsrv->cklen = strlen(args[cur_arg + 1]);
3744 cur_arg += 2;
3745 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003746 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003747 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3748 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3749 cur_arg += 2;
3750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003752 if (!*args[cur_arg + 1]) {
3753 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3754 file, linenum, args[cur_arg]);
3755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
3757 }
3758
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003760 if (newsrv->rise <= 0) {
3761 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3762 file, linenum, args[cur_arg]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
3766
Willy Tarreau96839092010-03-29 10:02:24 +02003767 if (newsrv->health)
3768 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 cur_arg += 2;
3770 }
3771 else if (!strcmp(args[cur_arg], "fall")) {
3772 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003773
3774 if (!*args[cur_arg + 1]) {
3775 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3776 file, linenum, args[cur_arg]);
3777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
3779 }
3780
3781 if (newsrv->fall <= 0) {
3782 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3783 file, linenum, args[cur_arg]);
3784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
3786 }
3787
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 cur_arg += 2;
3789 }
3790 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003791 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3792 if (err) {
3793 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3794 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003797 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003798 if (val <= 0) {
3799 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3800 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003803 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003804 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 cur_arg += 2;
3806 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003807 else if (!strcmp(args[cur_arg], "fastinter")) {
3808 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3809 if (err) {
3810 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3811 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003814 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003815 if (val <= 0) {
3816 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3817 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003820 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003821 newsrv->fastinter = val;
3822 cur_arg += 2;
3823 }
3824 else if (!strcmp(args[cur_arg], "downinter")) {
3825 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3826 if (err) {
3827 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3828 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003831 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003832 if (val <= 0) {
3833 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3834 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003837 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003838 newsrv->downinter = val;
3839 cur_arg += 2;
3840 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003841 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003842 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3843 if (!sk) {
3844 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003849 cur_arg += 2;
3850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 else if (!strcmp(args[cur_arg], "port")) {
3852 newsrv->check_port = atol(args[cur_arg + 1]);
3853 cur_arg += 2;
3854 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003855 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 newsrv->state |= SRV_BACKUP;
3857 cur_arg ++;
3858 }
3859 else if (!strcmp(args[cur_arg], "weight")) {
3860 int w;
3861 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003862 if (w < 0 || w > 256) {
3863 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003868 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 cur_arg += 2;
3870 }
3871 else if (!strcmp(args[cur_arg], "minconn")) {
3872 newsrv->minconn = atol(args[cur_arg + 1]);
3873 cur_arg += 2;
3874 }
3875 else if (!strcmp(args[cur_arg], "maxconn")) {
3876 newsrv->maxconn = atol(args[cur_arg + 1]);
3877 cur_arg += 2;
3878 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003879 else if (!strcmp(args[cur_arg], "maxqueue")) {
3880 newsrv->maxqueue = atol(args[cur_arg + 1]);
3881 cur_arg += 2;
3882 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003883 else if (!strcmp(args[cur_arg], "slowstart")) {
3884 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003885 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003886 if (err) {
3887 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3888 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003891 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003892 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003893 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3894 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003897 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003898 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003899 cur_arg += 2;
3900 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003901 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003902
3903 if (!*args[cur_arg + 1]) {
3904 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3905 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003908 }
3909
3910 newsrv->trackit = strdup(args[cur_arg + 1]);
3911
3912 cur_arg += 2;
3913 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003914 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 global.maxsock++;
3916 do_check = 1;
3917 cur_arg += 1;
3918 }
Willy Tarreau96839092010-03-29 10:02:24 +02003919 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3920 newsrv->state |= SRV_MAINTAIN;
3921 newsrv->state &= ~SRV_RUNNING;
3922 newsrv->health = 0;
3923 cur_arg += 1;
3924 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003925 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003926 if (!strcmp(args[cur_arg + 1], "none"))
3927 newsrv->observe = HANA_OBS_NONE;
3928 else if (!strcmp(args[cur_arg + 1], "layer4"))
3929 newsrv->observe = HANA_OBS_LAYER4;
3930 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3931 if (curproxy->mode != PR_MODE_HTTP) {
3932 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3933 file, linenum, args[cur_arg + 1]);
3934 err_code |= ERR_ALERT;
3935 }
3936 newsrv->observe = HANA_OBS_LAYER7;
3937 }
3938 else {
3939 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003940 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003941 file, linenum, args[cur_arg], args[cur_arg + 1]);
3942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
3944 }
3945
3946 cur_arg += 2;
3947 }
3948 else if (!strcmp(args[cur_arg], "on-error")) {
3949 if (!strcmp(args[cur_arg + 1], "fastinter"))
3950 newsrv->onerror = HANA_ONERR_FASTINTER;
3951 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3952 newsrv->onerror = HANA_ONERR_FAILCHK;
3953 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3954 newsrv->onerror = HANA_ONERR_SUDDTH;
3955 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3956 newsrv->onerror = HANA_ONERR_MARKDWN;
3957 else {
3958 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003959 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003960 file, linenum, args[cur_arg], args[cur_arg + 1]);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
3964
3965 cur_arg += 2;
3966 }
3967 else if (!strcmp(args[cur_arg], "error-limit")) {
3968 if (!*args[cur_arg + 1]) {
3969 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3970 file, linenum, args[cur_arg]);
3971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
3973 }
3974
3975 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3976
3977 if (newsrv->consecutive_errors_limit <= 0) {
3978 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3979 file, linenum, args[cur_arg]);
3980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
3982 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003983 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003984 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003985 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003986 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003987 struct sockaddr_in *sk;
3988
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003990#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003991 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003992 file, linenum, "source", "usesrc");
3993#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003994 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003996#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 }
4000 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004001 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4002 if (!sk) {
4003 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
4006 }
4007 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004008
4009 if (port_low != port_high) {
4010 int i;
4011 if (port_low <= 0 || port_low > 65535 ||
4012 port_high <= 0 || port_high > 65535 ||
4013 port_low > port_high) {
4014 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4015 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004018 }
4019 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4020 for (i = 0; i < newsrv->sport_range->size; i++)
4021 newsrv->sport_range->ports[i] = port_low + i;
4022 }
4023
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004025 while (*(args[cur_arg])) {
4026 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004027#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4028#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004029 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4030 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4031 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004034 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004035#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004036 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004037 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004038 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004041 }
4042 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004043 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004044 newsrv->state |= SRV_TPROXY_CLI;
4045 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004046 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004047 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004048 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4049 char *name, *end;
4050
4051 name = args[cur_arg+1] + 7;
4052 while (isspace(*name))
4053 name++;
4054
4055 end = name;
4056 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4057 end++;
4058
4059 newsrv->state &= ~SRV_TPROXY_MASK;
4060 newsrv->state |= SRV_TPROXY_DYN;
4061 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4062 newsrv->bind_hdr_len = end - name;
4063 memcpy(newsrv->bind_hdr_name, name, end - name);
4064 newsrv->bind_hdr_name[end-name] = '\0';
4065 newsrv->bind_hdr_occ = -1;
4066
4067 /* now look for an occurrence number */
4068 while (isspace(*end))
4069 end++;
4070 if (*end == ',') {
4071 end++;
4072 name = end;
4073 if (*end == '-')
4074 end++;
4075 while (isdigit(*end))
4076 end++;
4077 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4078 }
4079
4080 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4081 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4082 " occurrences values smaller than %d.\n",
4083 file, linenum, MAX_HDR_HISTORY);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004087 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004088 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4089 if (!sk) {
4090 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
4093 }
4094 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004095 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004096 }
4097 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004098#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004099 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004100#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004101 cur_arg += 2;
4102 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004103#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004104 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004105 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004108#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4109 } /* "usesrc" */
4110
4111 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4112#ifdef SO_BINDTODEVICE
4113 if (!*args[cur_arg + 1]) {
4114 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4115 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004118 }
4119 if (newsrv->iface_name)
4120 free(newsrv->iface_name);
4121
4122 newsrv->iface_name = strdup(args[cur_arg + 1]);
4123 newsrv->iface_len = strlen(newsrv->iface_name);
4124 global.last_checks |= LSTCHK_NETADM;
4125#else
4126 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4127 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004130#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004131 cur_arg += 2;
4132 continue;
4133 }
4134 /* this keyword in not an option of "source" */
4135 break;
4136 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004138 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004139 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4140 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004145 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004146 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004147 file, linenum, newsrv->id);
4148 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004149 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 +01004150 file, linenum);
4151
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
4155 }
4156
4157 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004158 if (newsrv->trackit) {
4159 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4160 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004163 }
4164
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004165 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4166 newsrv->check_port = newsrv->check_addr.sin_port;
4167
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4169 newsrv->check_port = realport; /* by default */
4170 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004171 /* not yet valid, because no port was set on
4172 * the server either. We'll check if we have
4173 * a known port on the first listener.
4174 */
4175 struct listener *l;
4176 l = curproxy->listen;
4177 if (l) {
4178 int port;
4179 port = (l->addr.ss_family == AF_INET6)
4180 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4181 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4182 newsrv->check_port = port;
4183 }
4184 }
4185 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4187 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004191
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004192 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004193 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004194 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4195 err_code |= ERR_ALERT | ERR_ABORT;
4196 goto out;
4197 }
4198
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004199 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 newsrv->state |= SRV_CHECKED;
4201 }
4202
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004203 if (!defsrv) {
4204 if (newsrv->state & SRV_BACKUP)
4205 curproxy->srv_bck++;
4206 else
4207 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004208
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004209 newsrv->prev_state = newsrv->state;
4210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 }
4212 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004213 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 int facility;
4215
4216 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4217 curproxy->logfac1 = global.logfac1;
4218 curproxy->logsrv1 = global.logsrv1;
4219 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004220 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 curproxy->logfac2 = global.logfac2;
4222 curproxy->logsrv2 = global.logsrv2;
4223 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004224 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 }
4226 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004227 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228
4229 facility = get_log_facility(args[2]);
4230 if (facility < 0) {
4231 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4232 exit(1);
4233 }
4234
4235 level = 7; /* max syslog level = debug */
4236 if (*(args[3])) {
4237 level = get_log_level(args[3]);
4238 if (level < 0) {
4239 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4240 exit(1);
4241 }
4242 }
4243
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004244 minlvl = 0; /* limit syslog level to this level (emerg) */
4245 if (*(args[4])) {
4246 minlvl = get_log_level(args[4]);
4247 if (level < 0) {
4248 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4249 exit(1);
4250 }
4251 }
4252
Robert Tsai81ae1952007-12-05 10:47:29 +01004253 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004254 struct sockaddr_un *sk = str2sun(args[1]);
4255 if (!sk) {
4256 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4257 args[1], (int)sizeof(sk->sun_path) - 1);
4258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
4260 }
4261 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004262 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004263 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004264 struct sockaddr_in *sk = str2sa(args[1]);
4265 if (!sk) {
4266 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004271 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004272 if (!logsrv.u.in.sin_port) {
4273 logsrv.u.in.sin_port =
4274 htons(SYSLOG_PORT);
4275 }
4276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277
4278 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004279 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 curproxy->logfac1 = facility;
4281 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004282 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 }
4284 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004285 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 curproxy->logfac2 = facility;
4287 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004288 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289 }
4290 else {
4291 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 }
4295 }
4296 else {
4297 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4298 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 }
4302 }
4303 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004304 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004305 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004306
Willy Tarreau977b8e42006-12-29 14:19:17 +01004307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004309
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004311 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4312 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004316
4317 /* we must first clear any optional default setting */
4318 curproxy->options &= ~PR_O_TPXY_MASK;
4319 free(curproxy->iface_name);
4320 curproxy->iface_name = NULL;
4321 curproxy->iface_len = 0;
4322
Willy Tarreaud5191e72010-02-09 20:50:45 +01004323 sk = str2sa(args[1]);
4324 if (!sk) {
4325 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
4328 }
4329 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004331
4332 cur_arg = 2;
4333 while (*(args[cur_arg])) {
4334 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004335#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4336#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004337 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4338 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4339 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004342 }
4343#endif
4344 if (!*args[cur_arg + 1]) {
4345 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4346 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004349 }
4350
4351 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004352 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004353 curproxy->options |= PR_O_TPXY_CLI;
4354 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004355 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004356 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004357 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4358 char *name, *end;
4359
4360 name = args[cur_arg+1] + 7;
4361 while (isspace(*name))
4362 name++;
4363
4364 end = name;
4365 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4366 end++;
4367
4368 curproxy->options &= ~PR_O_TPXY_MASK;
4369 curproxy->options |= PR_O_TPXY_DYN;
4370 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4371 curproxy->bind_hdr_len = end - name;
4372 memcpy(curproxy->bind_hdr_name, name, end - name);
4373 curproxy->bind_hdr_name[end-name] = '\0';
4374 curproxy->bind_hdr_occ = -1;
4375
4376 /* now look for an occurrence number */
4377 while (isspace(*end))
4378 end++;
4379 if (*end == ',') {
4380 end++;
4381 name = end;
4382 if (*end == '-')
4383 end++;
4384 while (isdigit(*end))
4385 end++;
4386 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4387 }
4388
4389 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4390 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4391 " occurrences values smaller than %d.\n",
4392 file, linenum, MAX_HDR_HISTORY);
4393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
4395 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004396 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004397 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4398 if (!sk) {
4399 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
4402 }
4403 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004404 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004405 }
4406 global.last_checks |= LSTCHK_NETADM;
4407#if !defined(CONFIG_HAP_LINUX_TPROXY)
4408 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004409#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004410#else /* no TPROXY support */
4411 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004412 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004415#endif
4416 cur_arg += 2;
4417 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004418 }
4419
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004420 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4421#ifdef SO_BINDTODEVICE
4422 if (!*args[cur_arg + 1]) {
4423 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4424 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004427 }
4428 if (curproxy->iface_name)
4429 free(curproxy->iface_name);
4430
4431 curproxy->iface_name = strdup(args[cur_arg + 1]);
4432 curproxy->iface_len = strlen(curproxy->iface_name);
4433 global.last_checks |= LSTCHK_NETADM;
4434#else
4435 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4436 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004439#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004440 cur_arg += 2;
4441 continue;
4442 }
4443 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4444 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004449 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4450 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4451 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004455 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004456 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004462
4463 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4464 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004465 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004466 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 }
4469 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004470 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4471 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004472 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004473 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
4476 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004477 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4478 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004479 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004480 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 }
4483 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004484 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4485 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004486 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004487 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
4490 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004491 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4492 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004493 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004494 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004497 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004498 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4499 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004500 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004501 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004502 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004503 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004504 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004505 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4506 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004507 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004508 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004509 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004510 }
4511 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4513 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004514 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004516 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004519 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4521 file, linenum, args[0]);
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 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004525
4526 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4527 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004528 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004529 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 }
4532 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004533 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4534 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004535 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004536 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004538 }
4539 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004540 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4541 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004542 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004543 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 }
4546 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004547 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4548 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004549 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004550 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004552 }
4553 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004554 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4555 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004556 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004557 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004559 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004560 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004561 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4562 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004563 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004564 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004565 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004568 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004569
Willy Tarreaubaaee002006-06-26 02:48:02 +02004570 if (curproxy == &defproxy) {
4571 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004575 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004577
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 if (*(args[1]) == 0) {
4579 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004583
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004584 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4585 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4586 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4587 file, linenum, args[0]);
4588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
4590 }
4591 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4592 }
4593 else if (*args[2]) {
4594 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4595 file, linenum, args[0], args[2]);
4596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
4598 }
4599
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004600 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004601 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004602 wl->s = strdup(args[1]);
4603 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004604 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 }
4606 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004607 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004613
Willy Tarreauade5ec42010-01-28 19:33:49 +01004614 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4615 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004616 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004617 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
4620 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004621 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4622 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004623 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004624 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 }
4627 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004628 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4629 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004630 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004631 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 }
4634 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004635 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4637 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 }
4641
Willy Tarreauade5ec42010-01-28 19:33:49 +01004642 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4643 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004644 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004645 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 }
4648 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004649 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4650 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004651 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004652 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004654 }
4655 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004656 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4657 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004658 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004659 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 }
4662 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004663 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004664
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 if (curproxy == &defproxy) {
4666 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004670 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004671 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 if (*(args[1]) == 0) {
4674 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
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
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004679 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4680 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4681 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4682 file, linenum, args[0]);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
4686 err_code |= warnif_cond_requires_req(cond, file, linenum);
4687 }
4688 else if (*args[2]) {
4689 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4690 file, linenum, args[0], args[2]);
4691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
4693 }
4694
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004695 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004696 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004697 wl->s = strdup(args[1]);
4698 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
4700 else if (!strcmp(args[0], "errorloc") ||
4701 !strcmp(args[0], "errorloc302") ||
4702 !strcmp(args[0], "errorloc303")) { /* error location */
4703 int errnum, errlen;
4704 char *err;
4705
Willy Tarreau977b8e42006-12-29 14:19:17 +01004706 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004707 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004708
Willy Tarreaubaaee002006-06-26 02:48:02 +02004709 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004710 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 }
4714
4715 errnum = atol(args[1]);
4716 if (!strcmp(args[0], "errorloc303")) {
4717 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4718 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4719 } else {
4720 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4721 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4722 }
4723
Willy Tarreau0f772532006-12-23 20:51:41 +01004724 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4725 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004726 chunk_destroy(&curproxy->errmsg[rc]);
4727 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004728 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004730 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004731
4732 if (rc >= HTTP_ERR_SIZE) {
4733 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4734 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 free(err);
4736 }
4737 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004738 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4739 int errnum, errlen, fd;
4740 char *err;
4741 struct stat stat;
4742
4743 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004745
4746 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004747 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004750 }
4751
4752 fd = open(args[2], O_RDONLY);
4753 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4754 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4755 file, linenum, args[2], args[1]);
4756 if (fd >= 0)
4757 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004760 }
4761
Willy Tarreau27a674e2009-08-17 07:23:33 +02004762 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004763 errlen = stat.st_size;
4764 } else {
4765 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004766 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004767 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004768 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004769 }
4770
4771 err = malloc(errlen); /* malloc() must succeed during parsing */
4772 errnum = read(fd, err, errlen);
4773 if (errnum != errlen) {
4774 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4775 file, linenum, args[2], args[1]);
4776 close(fd);
4777 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004780 }
4781 close(fd);
4782
4783 errnum = atol(args[1]);
4784 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4785 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004786 chunk_destroy(&curproxy->errmsg[rc]);
4787 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004788 break;
4789 }
4790 }
4791
4792 if (rc >= HTTP_ERR_SIZE) {
4793 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4794 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004795 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004796 free(err);
4797 }
4798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004800 struct cfg_kw_list *kwl;
4801 int index;
4802
4803 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4804 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4805 if (kwl->kw[index].section != CFG_LISTEN)
4806 continue;
4807 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4808 /* prepare error message just in case */
4809 snprintf(trash, sizeof(trash),
4810 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004811 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4812 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004813 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004816 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004817 else if (rc > 0) {
4818 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004819 err_code |= ERR_WARN;
4820 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004821 }
Willy Tarreau93893792009-07-23 13:19:11 +02004822 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004823 }
4824 }
4825 }
4826
Willy Tarreau6daf3432008-01-22 16:44:08 +01004827 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004828 err_code |= ERR_ALERT | ERR_FATAL;
4829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 }
Willy Tarreau93893792009-07-23 13:19:11 +02004831 out:
4832 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833}
4834
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004835int
4836cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4837{
4838
4839 int err_code = 0;
4840 const char *err;
4841
4842 if (!strcmp(args[0], "userlist")) { /* new userlist */
4843 struct userlist *newul;
4844
4845 if (!*args[1]) {
4846 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4847 file, linenum, args[0]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
4851
4852 err = invalid_char(args[1]);
4853 if (err) {
4854 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4855 file, linenum, *err, args[0], args[1]);
4856 err_code |= ERR_ALERT | ERR_FATAL;
4857 goto out;
4858 }
4859
4860 for (newul = userlist; newul; newul = newul->next)
4861 if (!strcmp(newul->name, args[1])) {
4862 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4863 file, linenum, args[1]);
4864 err_code |= ERR_WARN;
4865 goto out;
4866 }
4867
4868 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4869 if (!newul) {
4870 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4871 err_code |= ERR_ALERT | ERR_ABORT;
4872 goto out;
4873 }
4874
4875 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4876 newul->name = strdup(args[1]);
4877
4878 if (!newul->groupusers | !newul->name) {
4879 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4880 err_code |= ERR_ALERT | ERR_ABORT;
4881 goto out;
4882 }
4883
4884 newul->next = userlist;
4885 userlist = newul;
4886
4887 } else if (!strcmp(args[0], "group")) { /* new group */
4888 int cur_arg, i;
4889 const char *err;
4890
4891 if (!*args[1]) {
4892 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4893 file, linenum, args[0]);
4894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
4896 }
4897
4898 err = invalid_char(args[1]);
4899 if (err) {
4900 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4901 file, linenum, *err, args[0], args[1]);
4902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
4904 }
4905
4906 for(i = 0; i < userlist->grpcnt; i++)
4907 if (!strcmp(userlist->groups[i], args[1])) {
4908 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4909 file, linenum, args[1], userlist->name);
4910 err_code |= ERR_ALERT;
4911 goto out;
4912 }
4913
4914 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4915 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4916 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
4919 }
4920
4921 cur_arg = 2;
4922
4923 while (*args[cur_arg]) {
4924 if (!strcmp(args[cur_arg], "users")) {
4925 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4926 cur_arg += 2;
4927 continue;
4928 } else {
4929 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4930 file, linenum, args[0]);
4931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
4933 }
4934 }
4935
4936 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4937 } else if (!strcmp(args[0], "user")) { /* new user */
4938 struct auth_users *newuser;
4939 int cur_arg;
4940
4941 if (!*args[1]) {
4942 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4943 file, linenum, args[0]);
4944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
4946 }
4947
4948 for (newuser = userlist->users; newuser; newuser = newuser->next)
4949 if (!strcmp(newuser->user, args[1])) {
4950 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4951 file, linenum, args[1], userlist->name);
4952 err_code |= ERR_ALERT;
4953 goto out;
4954 }
4955
4956 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4957 if (!newuser) {
4958 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4959 err_code |= ERR_ALERT | ERR_ABORT;
4960 goto out;
4961 }
4962
4963 newuser->user = strdup(args[1]);
4964
4965 newuser->next = userlist->users;
4966 userlist->users = newuser;
4967
4968 cur_arg = 2;
4969
4970 while (*args[cur_arg]) {
4971 if (!strcmp(args[cur_arg], "password")) {
4972#ifndef CONFIG_HAP_CRYPT
4973 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4974 file, linenum);
4975 err_code |= ERR_ALERT;
4976#endif
4977 newuser->pass = strdup(args[cur_arg + 1]);
4978 cur_arg += 2;
4979 continue;
4980 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4981 newuser->pass = strdup(args[cur_arg + 1]);
4982 newuser->flags |= AU_O_INSECURE;
4983 cur_arg += 2;
4984 continue;
4985 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004986 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004987 cur_arg += 2;
4988 continue;
4989 } else {
4990 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4991 file, linenum, args[0]);
4992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
4994 }
4995 }
4996 } else {
4997 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4998 err_code |= ERR_ALERT | ERR_FATAL;
4999 }
5000
5001out:
5002 return err_code;
5003}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004
5005/*
5006 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005007 * Returns the error code, 0 if OK, or any combination of :
5008 * - ERR_ABORT: must abort ASAP
5009 * - ERR_FATAL: we can continue parsing but not start the service
5010 * - ERR_WARN: a warning has been emitted
5011 * - ERR_ALERT: an alert has been emitted
5012 * Only the two first ones can stop processing, the two others are just
5013 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005015int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005017 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 FILE *f;
5019 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005021 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 if ((f=fopen(file,"r")) == NULL)
5024 return -1;
5025
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005026 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005027 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005028 char *end;
5029 char *args[MAX_LINE_ARGS + 1];
5030 char *line = thisline;
5031
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 linenum++;
5033
5034 end = line + strlen(line);
5035
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005036 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5037 /* Check if we reached the limit and the last char is not \n.
5038 * Watch out for the last line without the terminating '\n'!
5039 */
5040 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005041 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005043 }
5044
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005046 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 line++;
5048
5049 arg = 0;
5050 args[arg] = line;
5051
5052 while (*line && arg < MAX_LINE_ARGS) {
5053 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5054 * C equivalent value. Other combinations left unchanged (eg: \1).
5055 */
5056 if (*line == '\\') {
5057 int skip = 0;
5058 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5059 *line = line[1];
5060 skip = 1;
5061 }
5062 else if (line[1] == 'r') {
5063 *line = '\r';
5064 skip = 1;
5065 }
5066 else if (line[1] == 'n') {
5067 *line = '\n';
5068 skip = 1;
5069 }
5070 else if (line[1] == 't') {
5071 *line = '\t';
5072 skip = 1;
5073 }
5074 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005075 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 unsigned char hex1, hex2;
5077 hex1 = toupper(line[2]) - '0';
5078 hex2 = toupper(line[3]) - '0';
5079 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5080 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5081 *line = (hex1<<4) + hex2;
5082 skip = 3;
5083 }
5084 else {
5085 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 }
5088 }
5089 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005090 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 end -= skip;
5092 }
5093 line++;
5094 }
5095 else if (*line == '#' || *line == '\n' || *line == '\r') {
5096 /* end of string, end of loop */
5097 *line = 0;
5098 break;
5099 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005100 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005102 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005103 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 line++;
5105 args[++arg] = line;
5106 }
5107 else {
5108 line++;
5109 }
5110 }
5111
5112 /* empty line */
5113 if (!**args)
5114 continue;
5115
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005116 if (*line) {
5117 /* we had to stop due to too many args.
5118 * Let's terminate the string, print the offending part then cut the
5119 * last arg.
5120 */
5121 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5122 line++;
5123 *line = '\0';
5124
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005125 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005126 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 args[arg] = line;
5129 }
5130
Willy Tarreau540abe42007-05-02 20:50:16 +02005131 /* zero out remaining args and ensure that at least one entry
5132 * is zeroed out.
5133 */
5134 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 args[arg] = line;
5136 }
5137
Willy Tarreau3842f002009-06-14 11:39:52 +02005138 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005139 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005140 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005141 for (arg=0; *args[arg+1]; arg++)
5142 args[arg] = args[arg+1]; // shift args after inversion
5143 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005144 else if (!strcmp(args[0], "default")) {
5145 kwm = KWM_DEF;
5146 for (arg=0; *args[arg+1]; arg++)
5147 args[arg] = args[arg+1]; // shift args after inversion
5148 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005149
Willy Tarreau3842f002009-06-14 11:39:52 +02005150 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5151 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005152 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005153 }
5154
Willy Tarreau977b8e42006-12-29 14:19:17 +01005155 if (!strcmp(args[0], "listen") ||
5156 !strcmp(args[0], "frontend") ||
5157 !strcmp(args[0], "backend") ||
5158 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005159 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005161 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005162 cursection = strdup(args[0]);
5163 }
5164 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005166 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005167 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005168 } else if (!strcmp(args[0], "userlist")) {
5169 confsect = CFG_USERLIST;
5170 free(cursection);
5171 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 /* else it's a section keyword */
5174
5175 switch (confsect) {
5176 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 break;
5179 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005180 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005182 case CFG_USERLIST:
5183 err_code |= cfg_parse_users(file, linenum, args, kwm);
5184 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005186 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005187 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005189
5190 if (err_code & ERR_ABORT)
5191 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005193 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005194 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005196 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005197}
5198
Willy Tarreaubb925012009-07-23 13:36:36 +02005199/*
5200 * Returns the error code, 0 if OK, or any combination of :
5201 * - ERR_ABORT: must abort ASAP
5202 * - ERR_FATAL: we can continue parsing but not start the service
5203 * - ERR_WARN: a warning has been emitted
5204 * - ERR_ALERT: an alert has been emitted
5205 * Only the two first ones can stop processing, the two others are just
5206 * indicators.
5207 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005208int check_config_validity()
5209{
5210 int cfgerr = 0;
5211 struct proxy *curproxy = NULL;
5212 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005213 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005214 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005215 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216
5217 /*
5218 * Now, check for the integrity of all that we have collected.
5219 */
5220
5221 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005222 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005224 /* first, we will invert the proxy list order */
5225 curproxy = NULL;
5226 while (proxy) {
5227 struct proxy *next;
5228
5229 next = proxy->next;
5230 proxy->next = curproxy;
5231 curproxy = proxy;
5232 if (!next)
5233 break;
5234 proxy = next;
5235 }
5236
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005238 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 }
5242
5243 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005244 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005245 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005246 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005247 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005248 unsigned int next_id;
5249
5250 if (!curproxy->uuid) {
5251 /* proxy ID not set, use automatic numbering with first
5252 * spare entry starting with next_pxid.
5253 */
5254 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5255 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5256 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005257 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005258 next_pxid++;
5259
Willy Tarreau55ea7572007-06-17 19:56:27 +02005260
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005262 /* ensure we don't keep listeners uselessly bound */
5263 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 curproxy = curproxy->next;
5265 continue;
5266 }
5267
Willy Tarreauff01a212009-03-15 13:46:16 +01005268 switch (curproxy->mode) {
5269 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005270 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005271 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005272 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5273 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005274 cfgerr++;
5275 }
5276
5277 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005278 Warning("config : servers will be ignored for %s '%s'.\n",
5279 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005280 break;
5281
5282 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005283 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005284 break;
5285
5286 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005287 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005288 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005289 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5290 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005291 cfgerr++;
5292 }
5293 break;
5294 }
5295
5296 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005297 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5298 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 cfgerr++;
5300 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005301
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005302 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005303 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005304 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005305 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5306 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005307 cfgerr++;
5308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005310 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005311 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5312 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005313 cfgerr++;
5314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005316 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005317 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5318 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005319 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005320 }
5321 }
5322 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5323 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5324 /* If no LB algo is set in a backend, and we're not in
5325 * transparent mode, dispatch mode nor proxy mode, we
5326 * want to use balance roundrobin by default.
5327 */
5328 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5329 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
5331 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005332
Willy Tarreau82936582007-11-30 15:20:09 +01005333 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5334 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005335 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5336 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005337 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005338 }
5339
Willy Tarreauef781042010-01-27 11:53:01 +01005340 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5341 curproxy->options &= ~PR_O2_CHK_SNDST;
5342 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5343 "send-state", proxy_type_str(curproxy), curproxy->id);
5344 err_code |= ERR_WARN;
5345 }
5346
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005347 /* if a default backend was specified, let's find it */
5348 if (curproxy->defbe.name) {
5349 struct proxy *target;
5350
Alex Williams96532db2009-11-01 21:27:13 -05005351 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005352 if (!target) {
5353 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5354 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005355 cfgerr++;
5356 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005357 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5358 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005359 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005360 } else {
5361 free(curproxy->defbe.name);
5362 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005363 /* we force the backend to be present on at least all of
5364 * the frontend's processes.
5365 */
5366 target->bind_proc = curproxy->bind_proc ?
5367 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
5369 }
5370
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005371 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005372 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5373 /* map jump target for ACT_SETBE in req_rep chain */
5374 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005375 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005376 struct proxy *target;
5377
Willy Tarreaua496b602006-12-17 23:15:24 +01005378 if (exp->action != ACT_SETBE)
5379 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005380
Alex Williams96532db2009-11-01 21:27:13 -05005381 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005382 if (!target) {
5383 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5384 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005385 cfgerr++;
5386 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005387 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5388 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005389 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005390 } else {
5391 free((void *)exp->replace);
5392 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005393 /* we force the backend to be present on at least all of
5394 * the frontend's processes.
5395 */
5396 target->bind_proc = curproxy->bind_proc ?
5397 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005398 }
5399 }
5400 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005401
5402 /* find the target proxy for 'use_backend' rules */
5403 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005404 struct proxy *target;
5405
Alex Williams96532db2009-11-01 21:27:13 -05005406 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005407
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005408 if (!target) {
5409 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5410 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005411 cfgerr++;
5412 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005413 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5414 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005415 cfgerr++;
5416 } else {
5417 free((void *)rule->be.name);
5418 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005419 /* we force the backend to be present on at least all of
5420 * the frontend's processes.
5421 */
5422 target->bind_proc = curproxy->bind_proc ?
5423 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005424 }
5425 }
5426
Emeric Brunb982a3d2010-01-04 15:45:53 +01005427 /* find the target table for 'stick' rules */
5428 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5429 struct proxy *target;
5430
Emeric Brun1d33b292010-01-04 15:47:17 +01005431 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5432 if (mrule->flags & STK_IS_STORE)
5433 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5434
Emeric Brunb982a3d2010-01-04 15:45:53 +01005435 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005436 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005437 else
5438 target = curproxy;
5439
5440 if (!target) {
5441 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5442 curproxy->id, mrule->table.name);
5443 cfgerr++;
5444 }
5445 else if (target->table.size == 0) {
5446 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5447 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5448 cfgerr++;
5449 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005450 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005451 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5452 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5453 cfgerr++;
5454 }
5455 else {
5456 free((void *)mrule->table.name);
5457 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005458 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005459 }
5460 }
5461
5462 /* find the target table for 'store response' rules */
5463 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5464 struct proxy *target;
5465
Emeric Brun1d33b292010-01-04 15:47:17 +01005466 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5467
Emeric Brunb982a3d2010-01-04 15:45:53 +01005468 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005469 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005470 else
5471 target = curproxy;
5472
5473 if (!target) {
5474 Alert("Proxy '%s': unable to find store table '%s'.\n",
5475 curproxy->id, mrule->table.name);
5476 cfgerr++;
5477 }
5478 else if (target->table.size == 0) {
5479 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5480 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5481 cfgerr++;
5482 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005483 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005484 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5485 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5486 cfgerr++;
5487 }
5488 else {
5489 free((void *)mrule->table.name);
5490 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005491 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005492 }
5493 }
5494
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005495 /* find the target table for 'tcp-request' layer 4 rules */
5496 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5497 struct proxy *target;
5498
Willy Tarreau56123282010-08-06 19:06:56 +02005499 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005500 continue;
5501
5502 if (trule->act_prm.trk_ctr.table.n)
5503 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5504 else
5505 target = curproxy;
5506
5507 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005508 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5509 curproxy->id, trule->act_prm.trk_ctr.table.n,
5510 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005511 cfgerr++;
5512 }
5513 else if (target->table.size == 0) {
5514 Alert("Proxy '%s': table '%s' used but not configured.\n",
5515 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5516 cfgerr++;
5517 }
5518 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005519 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 +02005520 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5521 cfgerr++;
5522 }
5523 else {
5524 free(trule->act_prm.trk_ctr.table.n);
5525 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005526 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005527 * to pass a list of counters to track and allocate them right here using
5528 * stktable_alloc_data_type().
5529 */
5530 }
5531 }
5532
Willy Tarreaud1f96522010-08-03 19:34:32 +02005533 /* find the target table for 'tcp-request' layer 6 rules */
5534 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5535 struct proxy *target;
5536
Willy Tarreau56123282010-08-06 19:06:56 +02005537 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005538 continue;
5539
5540 if (trule->act_prm.trk_ctr.table.n)
5541 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5542 else
5543 target = curproxy;
5544
5545 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005546 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5547 curproxy->id, trule->act_prm.trk_ctr.table.n,
5548 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005549 cfgerr++;
5550 }
5551 else if (target->table.size == 0) {
5552 Alert("Proxy '%s': table '%s' used but not configured.\n",
5553 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5554 cfgerr++;
5555 }
5556 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005557 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 +02005558 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5559 cfgerr++;
5560 }
5561 else {
5562 free(trule->act_prm.trk_ctr.table.n);
5563 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005564 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005565 * to pass a list of counters to track and allocate them right here using
5566 * stktable_alloc_data_type().
5567 */
5568 }
5569 }
5570
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005571 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5572 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005573 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5574 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5575 "proxy", curproxy->id);
5576 cfgerr++;
5577 goto out_uri_auth_compat;
5578 }
5579
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005580 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005581 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005582 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005583 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005584
Willy Tarreau95fa4692010-02-01 13:05:50 +01005585 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5586 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005587
5588 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005589 uri_auth_compat_req[i++] = "realm";
5590 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5591 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005592
Willy Tarreau95fa4692010-02-01 13:05:50 +01005593 uri_auth_compat_req[i++] = "unless";
5594 uri_auth_compat_req[i++] = "{";
5595 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5596 uri_auth_compat_req[i++] = "}";
5597 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005598
Willy Tarreau95fa4692010-02-01 13:05:50 +01005599 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5600 if (!req_acl) {
5601 cfgerr++;
5602 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005603 }
5604
Willy Tarreau95fa4692010-02-01 13:05:50 +01005605 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5606
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005607 if (curproxy->uri_auth->auth_realm) {
5608 free(curproxy->uri_auth->auth_realm);
5609 curproxy->uri_auth->auth_realm = NULL;
5610 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005611
5612 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005613 }
5614out_uri_auth_compat:
5615
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005616 cfgerr += acl_find_targets(curproxy);
5617
Willy Tarreau2738a142006-07-08 17:28:09 +02005618 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005619 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005620 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005621 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005622 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005623 " | While not properly invalid, you will certainly encounter various problems\n"
5624 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005625 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005626 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005627 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005628 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005629
Willy Tarreau1fa31262007-12-03 00:36:16 +01005630 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5631 * We must still support older configurations, so let's find out whether those
5632 * parameters have been set or must be copied from contimeouts.
5633 */
5634 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005635 if (!curproxy->timeout.tarpit ||
5636 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005637 /* tarpit timeout not set. We search in the following order:
5638 * default.tarpit, curr.connect, default.connect.
5639 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005640 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005641 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005642 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005643 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005644 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005645 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005646 }
5647 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005648 (!curproxy->timeout.queue ||
5649 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005650 /* queue timeout not set. We search in the following order:
5651 * default.queue, curr.connect, default.connect.
5652 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005653 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005654 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005655 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005656 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005657 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005658 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005659 }
5660 }
5661
Willy Tarreau07a54902010-03-29 18:33:29 +02005662 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005663 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5664 curproxy->check_req = (char *)malloc(curproxy->check_len);
5665 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005666 }
5667
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005668 /* The small pools required for the capture lists */
5669 if (curproxy->nb_req_cap)
5670 curproxy->req_cap_pool = create_pool("ptrcap",
5671 curproxy->nb_req_cap * sizeof(char *),
5672 MEM_F_SHARED);
5673 if (curproxy->nb_rsp_cap)
5674 curproxy->rsp_cap_pool = create_pool("ptrcap",
5675 curproxy->nb_rsp_cap * sizeof(char *),
5676 MEM_F_SHARED);
5677
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005678 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5679 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5680 MEM_F_SHARED);
5681
Willy Tarreau86034312006-12-29 00:10:33 +01005682 /* for backwards compatibility with "listen" instances, if
5683 * fullconn is not set but maxconn is set, then maxconn
5684 * is used.
5685 */
5686 if (!curproxy->fullconn)
5687 curproxy->fullconn = curproxy->maxconn;
5688
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 /* first, we will invert the servers list order */
5690 newsrv = NULL;
5691 while (curproxy->srv) {
5692 struct server *next;
5693
5694 next = curproxy->srv->next;
5695 curproxy->srv->next = newsrv;
5696 newsrv = curproxy->srv;
5697 if (!next)
5698 break;
5699 curproxy->srv = next;
5700 }
5701
Willy Tarreaudd701652010-05-25 23:03:02 +02005702 /* assign automatic UIDs to servers which don't have one yet */
5703 next_id = 1;
5704 newsrv = curproxy->srv;
5705 while (newsrv != NULL) {
5706 if (!newsrv->puid) {
5707 /* server ID not set, use automatic numbering with first
5708 * spare entry starting with next_svid.
5709 */
5710 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5711 newsrv->conf.id.key = newsrv->puid = next_id;
5712 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5713 }
5714 next_id++;
5715 newsrv = newsrv->next;
5716 }
5717
Willy Tarreau20697042007-11-15 23:26:18 +01005718 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005719 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005721 /* We have to initialize the server lookup mechanism depending
5722 * on what LB algorithm was choosen.
5723 */
5724
5725 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5726 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5727 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005728 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5729 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5730 init_server_map(curproxy);
5731 } else {
5732 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5733 fwrr_init_server_groups(curproxy);
5734 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005735 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005736
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005737 case BE_LB_KIND_LC:
5738 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005739 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005740 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005741
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005742 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005743 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5744 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5745 chash_init_server_tree(curproxy);
5746 } else {
5747 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5748 init_server_map(curproxy);
5749 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005750 break;
5751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752
5753 if (curproxy->options & PR_O_LOGASAP)
5754 curproxy->to_log &= ~LW_BYTES;
5755
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005756 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5757 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5758 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5759 proxy_type_str(curproxy), curproxy->id);
5760 err_code |= ERR_WARN;
5761 }
5762
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005763 if (curproxy->mode != PR_MODE_HTTP) {
5764 int optnum;
5765
5766 if (curproxy->options & PR_O_COOK_ANY) {
5767 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5768 proxy_type_str(curproxy), curproxy->id);
5769 err_code |= ERR_WARN;
5770 }
5771
5772 if (curproxy->uri_auth) {
5773 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5774 proxy_type_str(curproxy), curproxy->id);
5775 err_code |= ERR_WARN;
5776 curproxy->uri_auth = NULL;
5777 }
5778
5779 if (curproxy->options & PR_O_FWDFOR) {
5780 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5781 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5782 err_code |= ERR_WARN;
5783 curproxy->options &= ~PR_O_FWDFOR;
5784 }
5785
5786 if (curproxy->options & PR_O_ORGTO) {
5787 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5788 "originalto", proxy_type_str(curproxy), curproxy->id);
5789 err_code |= ERR_WARN;
5790 curproxy->options &= ~PR_O_ORGTO;
5791 }
5792
5793 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5794 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5795 (curproxy->cap & cfg_opts[optnum].cap) &&
5796 (curproxy->options & cfg_opts[optnum].val)) {
5797 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5798 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5799 err_code |= ERR_WARN;
5800 curproxy->options &= ~cfg_opts[optnum].val;
5801 }
5802 }
5803
5804 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5805 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5806 (curproxy->cap & cfg_opts2[optnum].cap) &&
5807 (curproxy->options2 & cfg_opts2[optnum].val)) {
5808 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5809 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5810 err_code |= ERR_WARN;
5811 curproxy->options2 &= ~cfg_opts2[optnum].val;
5812 }
5813 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005814
Willy Tarreauefa5f512010-03-30 20:13:29 +02005815#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005816 if (curproxy->bind_hdr_occ) {
5817 curproxy->bind_hdr_occ = 0;
5818 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5819 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5820 err_code |= ERR_WARN;
5821 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005822#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005823 }
5824
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005826 * ensure that we're not cross-dressing a TCP server into HTTP.
5827 */
5828 newsrv = curproxy->srv;
5829 while (newsrv != NULL) {
5830 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005831 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5832 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005833 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005834 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005835
Willy Tarreauefa5f512010-03-30 20:13:29 +02005836#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005837 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5838 newsrv->bind_hdr_occ = 0;
5839 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5840 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5841 err_code |= ERR_WARN;
5842 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005843#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005844 newsrv = newsrv->next;
5845 }
5846
5847 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 * If this server supports a maxconn parameter, it needs a dedicated
5849 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005850 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851 */
5852 newsrv = curproxy->srv;
5853 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005854 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 /* Only 'minconn' was specified, or it was higher than or equal
5856 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5857 * this will avoid further useless expensive computations.
5858 */
5859 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005860 } else if (newsrv->maxconn && !newsrv->minconn) {
5861 /* minconn was not specified, so we set it to maxconn */
5862 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005863 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005864 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5865 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005866 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 }
5868
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005869 if (newsrv->trackit) {
5870 struct proxy *px;
5871 struct server *srv;
5872 char *pname, *sname;
5873
5874 pname = newsrv->trackit;
5875 sname = strrchr(pname, '/');
5876
5877 if (sname)
5878 *sname++ = '\0';
5879 else {
5880 sname = pname;
5881 pname = NULL;
5882 }
5883
5884 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005885 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005886 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005887 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5888 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005889 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005890 cfgerr++;
5891 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005892 }
5893 } else
5894 px = curproxy;
5895
5896 srv = findserver(px, sname);
5897 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005898 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5899 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005900 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005901 cfgerr++;
5902 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005903 }
5904
5905 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005906 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005907 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005908 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005909 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005910 cfgerr++;
5911 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005912 }
5913
5914 if (curproxy != px &&
5915 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005916 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005917 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005918 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005919 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005920 cfgerr++;
5921 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005922 }
5923
5924 newsrv->tracked = srv;
5925 newsrv->tracknext = srv->tracknext;
5926 srv->tracknext = newsrv;
5927
5928 free(newsrv->trackit);
5929 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005930 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 newsrv = newsrv->next;
5932 }
5933
Willy Tarreauc1a21672009-08-16 22:37:44 +02005934 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005935 curproxy->accept = frontend_accept;
5936
Willy Tarreauc1a21672009-08-16 22:37:44 +02005937 if (curproxy->tcp_req.inspect_delay ||
5938 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02005939 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005940
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005941 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005942 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005943 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005944 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005945
5946 /* both TCP and HTTP must check switching rules */
5947 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5948 }
5949
5950 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02005951 if (curproxy->tcp_req.inspect_delay ||
5952 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5953 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
5954
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005955 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005956 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005957 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005958 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005959
5960 /* If the backend does requires RDP cookie persistence, we have to
5961 * enable the corresponding analyser.
5962 */
5963 if (curproxy->options2 & PR_O2_RDPC_PRST)
5964 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5965 }
5966
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005967 listener = NULL;
5968 while (curproxy->listen) {
5969 struct listener *next;
5970
5971 next = curproxy->listen->next;
5972 curproxy->listen->next = listener;
5973 listener = curproxy->listen;
5974
5975 if (!next)
5976 break;
5977
5978 curproxy->listen = next;
5979 }
5980
Willy Tarreaue6b98942007-10-29 01:09:36 +01005981 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005982 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005983 listener = curproxy->listen;
5984 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005985 if (!listener->luid) {
5986 /* listener ID not set, use automatic numbering with first
5987 * spare entry starting with next_luid.
5988 */
5989 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5990 listener->conf.id.key = listener->luid = next_id;
5991 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005992 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005993 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005994
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005995 /* enable separate counters */
5996 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5997 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5998 if (!listener->name) {
5999 sprintf(trash, "sock-%d", listener->luid);
6000 listener->name = strdup(trash);
6001 }
6002 }
6003
Willy Tarreaue6b98942007-10-29 01:09:36 +01006004 if (curproxy->options & PR_O_TCP_NOLING)
6005 listener->options |= LI_O_NOLINGER;
6006 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006007 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006008 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006009 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006010 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006011 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006012 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006013
Willy Tarreau8a956912010-10-15 14:27:08 +02006014 if (listener->options & LI_O_ACC_PROXY)
6015 listener->analysers |= AN_REQ_DECODE_PROXY;
6016
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006017 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6018 listener->options |= LI_O_TCP_RULES;
6019
Willy Tarreaude3041d2010-05-31 10:56:17 +02006020 if (curproxy->mon_mask.s_addr)
6021 listener->options |= LI_O_CHK_MONNET;
6022
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006023 /* smart accept mode is automatic in HTTP mode */
6024 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6025 (curproxy->mode == PR_MODE_HTTP &&
6026 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6027 listener->options |= LI_O_NOQUICKACK;
6028
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006029 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006030 listener = listener->next;
6031 }
6032
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 curproxy = curproxy->next;
6034 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006035
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006036 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6037 struct auth_users *curuser;
6038 int g;
6039
6040 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6041 unsigned int group_mask = 0;
6042 char *group = NULL;
6043
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006044 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006045 continue;
6046
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006047 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006048
6049 for (g = 0; g < curuserlist->grpcnt; g++)
6050 if (!strcmp(curuserlist->groups[g], group))
6051 break;
6052
6053 if (g == curuserlist->grpcnt) {
6054 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6055 curuserlist->name, group, curuser->user);
6056 err_code |= ERR_ALERT | ERR_FATAL;
6057 goto out;
6058 }
6059
6060 group_mask |= (1 << g);
6061 }
6062
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006063 free(curuser->u.groups);
6064 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006065 }
6066
6067 for (g = 0; g < curuserlist->grpcnt; g++) {
6068 char *user = NULL;
6069
6070 if (!curuserlist->groupusers[g])
6071 continue;
6072
6073 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6074 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6075 if (!strcmp(curuser->user, user))
6076 break;
6077
6078 if (!curuser) {
6079 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6080 curuserlist->name, user, curuserlist->groups[g]);
6081 err_code |= ERR_ALERT | ERR_FATAL;
6082 goto out;
6083 }
6084
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006085 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006086 }
6087
6088 free(curuserlist->groupusers[g]);
6089 }
6090
6091 free(curuserlist->groupusers);
6092
6093#ifdef DEBUG_AUTH
6094 for (g = 0; g < curuserlist->grpcnt; g++) {
6095 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6096
6097 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6098 if (curuser->group_mask & (1 << g))
6099 fprintf(stderr, " %s", curuser->user);
6100 }
6101
6102 fprintf(stderr, "\n");
6103 }
6104#endif
6105
6106 }
6107
Willy Tarreau056f5682010-06-06 15:51:11 +02006108 /* initialize stick-tables on backend capable proxies. This must not
6109 * be done earlier because the data size may be discovered while parsing
6110 * other proxies.
6111 */
6112 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006113 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006115 /*
6116 * Recount currently required checks.
6117 */
6118
6119 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6120 int optnum;
6121
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006122 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6123 if (curproxy->options & cfg_opts[optnum].val)
6124 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006125
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006126 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6127 if (curproxy->options2 & cfg_opts2[optnum].val)
6128 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006129 }
6130
Willy Tarreaubb925012009-07-23 13:36:36 +02006131 if (cfgerr > 0)
6132 err_code |= ERR_ALERT | ERR_FATAL;
6133 out:
6134 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135}
6136
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006137/*
6138 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6139 * parsing sessions.
6140 */
6141void cfg_register_keywords(struct cfg_kw_list *kwl)
6142{
6143 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6144}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006145
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006146/*
6147 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6148 */
6149void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6150{
6151 LIST_DEL(&kwl->list);
6152 LIST_INIT(&kwl->list);
6153}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154
6155/*
6156 * Local variables:
6157 * c-indent-level: 8
6158 * c-basic-offset: 8
6159 * End:
6160 */