blob: 0e36050947d0b2f95950c6fe1f4fbc8955b5bbb8 [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 Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020046#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020047#include <proto/lb_fwlc.h>
48#include <proto/lb_fwrr.h>
49#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010051#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020052#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010053#include <proto/protocols.h>
54#include <proto/proto_tcp.h>
55#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010056#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010058#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010060#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061
62
Willy Tarreauf3c69202006-07-09 16:42:34 +020063/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
64 * ssl-hello-chk option to ensure that the remote server speaks SSL.
65 *
66 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
67 */
68const char sslv3_client_hello_pkt[] = {
69 "\x16" /* ContentType : 0x16 = Hanshake */
70 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
71 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
72 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
73 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
74 "\x03\x00" /* Hello Version : 0x0300 = v3 */
75 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
76 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
77 "\x00" /* Session ID length : empty (no session ID) */
78 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
79 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
80 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
81 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
82 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
83 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
84 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
85 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
86 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
87 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
88 "\x00\x38" "\x00\x39" "\x00\x3A"
89 "\x01" /* Compression Length : 0x01 = 1 byte for types */
90 "\x00" /* Compression Type : 0x00 = NULL compression */
91};
92
Willy Tarreau3842f002009-06-14 11:39:52 +020093/* various keyword modifiers */
94enum kw_mod {
95 KWM_STD = 0, /* normal */
96 KWM_NO, /* "no" prefixed before the keyword */
97 KWM_DEF, /* "default" prefixed before the keyword */
98};
99
Willy Tarreau13943ab2006-12-31 00:24:10 +0100100/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100101struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102 const char *name;
103 unsigned int val;
104 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100106 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100107};
108
109/* proxy->options */
110static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100112 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
113 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
114 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
115 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
116 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
117 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
118 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
120 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
122 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
124 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
125 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
126 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
127 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100128#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100129 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100130#endif
131
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100133};
134
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100135/* proxy->options2 */
136static const struct cfg_opt cfg_opts2[] =
137{
138#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100139 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
140 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
141 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
144 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
145 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
146 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
147 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
148 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
149 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
150 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
151 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
152 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200153 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100154 { NULL, 0, 0, 0 }
155};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156
Willy Tarreau6daf3432008-01-22 16:44:08 +0100157static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200158static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
159int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100160int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200161
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200162/* List head of all known configuration keywords */
163static struct cfg_kw_list cfg_keywords = {
164 .list = LIST_HEAD_INIT(cfg_keywords.list)
165};
166
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167/*
168 * converts <str> to a list of listeners which are dynamically allocated.
169 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
170 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
171 * - <port> is a numerical port from 1 to 65535 ;
172 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
173 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200174 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200176static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177{
178 struct listener *l;
179 char *c, *next, *range, *dupstr;
180 int port, end;
181
182 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200183
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184 while (next && *next) {
185 struct sockaddr_storage ss;
186
187 str = next;
188 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100189 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 *next++ = 0;
191 }
192
193 /* 2) look for the addr/port delimiter, it's the last colon. */
194 if ((range = strrchr(str, ':')) == NULL) {
195 Alert("Missing port number: '%s'\n", str);
196 goto fail;
197 }
198
199 *range++ = 0;
200
201 if (strrchr(str, ':') != NULL) {
202 /* IPv6 address contains ':' */
203 memset(&ss, 0, sizeof(ss));
204 ss.ss_family = AF_INET6;
205
206 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
207 Alert("Invalid server address: '%s'\n", str);
208 goto fail;
209 }
210 }
211 else {
212 memset(&ss, 0, sizeof(ss));
213 ss.ss_family = AF_INET;
214
215 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
216 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
217 }
218 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
219 struct hostent *he;
220
221 if ((he = gethostbyname(str)) == NULL) {
222 Alert("Invalid server name: '%s'\n", str);
223 goto fail;
224 }
225 else
226 ((struct sockaddr_in *)&ss)->sin_addr =
227 *(struct in_addr *) *(he->h_addr_list);
228 }
229 }
230
231 /* 3) look for the port-end delimiter */
232 if ((c = strchr(range, '-')) != NULL) {
233 *c++ = 0;
234 end = atol(c);
235 }
236 else {
237 end = atol(range);
238 }
239
240 port = atol(range);
241
242 if (port < 1 || port > 65535) {
243 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
244 goto fail;
245 }
246
247 if (end < 1 || end > 65535) {
248 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
249 goto fail;
250 }
251
252 for (; port <= end; port++) {
253 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200254 l->next = curproxy->listen;
255 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
257 l->fd = -1;
258 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100259 l->state = LI_INIT;
260
261 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100263 tcpv6_add_listener(l);
264 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100266 tcpv4_add_listener(l);
267 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200268
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 } /* end for(port) */
271 } /* end while(next) */
272 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200273 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 fail:
275 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200276 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277}
278
Willy Tarreau977b8e42006-12-29 14:19:17 +0100279/*
280 * Sends a warning if proxy <proxy> does not have at least one of the
281 * capabilities in <cap>. An optionnal <hint> may be added at the end
282 * of the warning to help the user. Returns 1 if a warning was emitted
283 * or 0 if the condition is valid.
284 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100285int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100286{
287 char *msg;
288
289 switch (cap) {
290 case PR_CAP_BE: msg = "no backend"; break;
291 case PR_CAP_FE: msg = "no frontend"; break;
292 case PR_CAP_RS: msg = "no ruleset"; break;
293 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
294 default: msg = "not enough"; break;
295 }
296
297 if (!(proxy->cap & cap)) {
298 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100299 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100300 return 1;
301 }
302 return 0;
303}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304
Willy Tarreau61d18892009-03-31 10:49:21 +0200305/* Report a warning if a rule is placed after a 'block' rule.
306 * Return 1 if the warning has been emitted, otherwise 0.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200309{
310 if (!LIST_ISEMPTY(&proxy->block_cond)) {
311 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
312 file, line, arg);
313 return 1;
314 }
315 return 0;
316}
317
318/* Report a warning if a rule is placed after a reqrewrite rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (proxy->req_exp) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqadd rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100336 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a redirect rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
349 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a 'use_backend' rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
374 warnif_rule_after_reqadd(proxy, file, line, arg) ||
375 warnif_rule_after_redirect(proxy, file, line, arg) ||
376 warnif_rule_after_use_backend(proxy, file, line, arg);
377}
378
379/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
383 warnif_rule_after_redirect(proxy, file, line, arg) ||
384 warnif_rule_after_use_backend(proxy, file, line, arg);
385}
386
387/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 return warnif_rule_after_redirect(proxy, file, line, arg) ||
391 warnif_rule_after_use_backend(proxy, file, line, arg);
392}
393
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100394/* Report it if a request ACL condition uses some response-only parameters. It
395 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
396 * Note that <cond> may be NULL and then will be ignored.
397 */
398static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
399{
400 struct acl *acl;
401
402 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
403 return 0;
404
405 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
406 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
407 file, line, acl ? acl->name : "(unknown)");
408 return ERR_WARN;
409}
410
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100411/* Report it if a request ACL condition uses some request-only volatile parameters.
412 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
413 * Note that <cond> may be NULL and then will be ignored.
414 */
415static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
416{
417 struct acl *acl;
418
419 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
420 return 0;
421
422 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
423 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
424 file, line, acl ? acl->name : "(unknown)");
425 return ERR_WARN;
426}
427
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200430 * parse a line in a <global> section. Returns the error code, 0 if OK, or
431 * any combination of :
432 * - ERR_ABORT: must abort ASAP
433 * - ERR_FATAL: we can continue parsing but not start the service
434 * - ERR_WARN: a warning has been emitted
435 * - ERR_ALERT: an alert has been emitted
436 * Only the two first ones can stop processing, the two others are just
437 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200439int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440{
Willy Tarreau058e9072009-07-20 09:30:05 +0200441 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442
443 if (!strcmp(args[0], "global")) { /* new section */
444 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200446 }
447 else if (!strcmp(args[0], "daemon")) {
448 global.mode |= MODE_DAEMON;
449 }
450 else if (!strcmp(args[0], "debug")) {
451 global.mode |= MODE_DEBUG;
452 }
453 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100454 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200456 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100457 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200458 }
459 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100460 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100463 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100465 else if (!strcmp(args[0], "nosplice")) {
466 global.tune.options &= ~GTUNE_USE_SPLICE;
467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 else if (!strcmp(args[0], "quiet")) {
469 global.mode |= MODE_QUIET;
470 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200471 else if (!strcmp(args[0], "tune.maxpollevents")) {
472 if (global.tune.maxpollevents != 0) {
473 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200474 err_code |= ERR_ALERT;
475 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200476 }
477 if (*(args[1]) == 0) {
478 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200479 err_code |= ERR_ALERT | ERR_FATAL;
480 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200481 }
482 global.tune.maxpollevents = atol(args[1]);
483 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100484 else if (!strcmp(args[0], "tune.maxaccept")) {
485 if (global.tune.maxaccept != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100494 }
495 global.tune.maxaccept = atol(args[1]);
496 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200497 else if (!strcmp(args[0], "tune.bufsize")) {
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.tune.bufsize = atol(args[1]);
504 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
505 global.tune.maxrewrite = global.tune.bufsize / 2;
506 }
507 else if (!strcmp(args[0], "tune.maxrewrite")) {
508 if (*(args[1]) == 0) {
509 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
510 err_code |= ERR_ALERT | ERR_FATAL;
511 goto out;
512 }
513 global.tune.maxrewrite = atol(args[1]);
514 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
515 global.tune.maxrewrite = global.tune.bufsize / 2;
516 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100517 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
518 if (global.tune.client_rcvbuf != 0) {
519 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
520 err_code |= ERR_ALERT;
521 goto out;
522 }
523 if (*(args[1]) == 0) {
524 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
527 }
528 global.tune.client_rcvbuf = atol(args[1]);
529 }
530 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
531 if (global.tune.server_rcvbuf != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT;
534 goto out;
535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
540 }
541 global.tune.server_rcvbuf = atol(args[1]);
542 }
543 else if (!strcmp(args[0], "tune.sndbuf.client")) {
544 if (global.tune.client_sndbuf != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT;
547 goto out;
548 }
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.client_sndbuf = atol(args[1]);
555 }
556 else if (!strcmp(args[0], "tune.sndbuf.server")) {
557 if (global.tune.server_sndbuf != 0) {
558 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT;
560 goto out;
561 }
562 if (*(args[1]) == 0) {
563 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566 }
567 global.tune.server_sndbuf = atol(args[1]);
568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 else if (!strcmp(args[0], "uid")) {
570 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200571 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200572 err_code |= ERR_ALERT;
573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 }
580 global.uid = atol(args[1]);
581 }
582 else if (!strcmp(args[0], "gid")) {
583 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200584 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200585 err_code |= ERR_ALERT;
586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 }
593 global.gid = atol(args[1]);
594 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200595 /* user/group name handling */
596 else if (!strcmp(args[0], "user")) {
597 struct passwd *ha_user;
598 if (global.uid != 0) {
599 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200600 err_code |= ERR_ALERT;
601 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200602 }
603 errno = 0;
604 ha_user = getpwnam(args[1]);
605 if (ha_user != NULL) {
606 global.uid = (int)ha_user->pw_uid;
607 }
608 else {
609 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 +0200610 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200611 }
612 }
613 else if (!strcmp(args[0], "group")) {
614 struct group *ha_group;
615 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200616 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200617 err_code |= ERR_ALERT;
618 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200619 }
620 errno = 0;
621 ha_group = getgrnam(args[1]);
622 if (ha_group != NULL) {
623 global.gid = (int)ha_group->gr_gid;
624 }
625 else {
626 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 +0200627 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200628 }
629 }
630 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 else if (!strcmp(args[0], "nbproc")) {
632 if (global.nbproc != 0) {
633 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.nbproc = atol(args[1]);
643 }
644 else if (!strcmp(args[0], "maxconn")) {
645 if (global.maxconn != 0) {
646 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT;
648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 }
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
655 global.maxconn = atol(args[1]);
656#ifdef SYSTEM_MAXCONN
657 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
658 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);
659 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
662#endif /* SYSTEM_MAXCONN */
663 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100664 else if (!strcmp(args[0], "maxpipes")) {
665 if (global.maxpipes != 0) {
666 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200667 err_code |= ERR_ALERT;
668 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100669 }
670 if (*(args[1]) == 0) {
671 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100674 }
675 global.maxpipes = atol(args[1]);
676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "ulimit-n")) {
678 if (global.rlimit_nofile != 0) {
679 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT;
681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683 if (*(args[1]) == 0) {
684 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200685 err_code |= ERR_ALERT | ERR_FATAL;
686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 }
688 global.rlimit_nofile = atol(args[1]);
689 }
690 else if (!strcmp(args[0], "chroot")) {
691 if (global.chroot != NULL) {
692 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT;
694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 }
696 if (*(args[1]) == 0) {
697 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 err_code |= ERR_ALERT | ERR_FATAL;
699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 }
701 global.chroot = strdup(args[1]);
702 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200703 else if (!strcmp(args[0], "description")) {
704 int i, len=0;
705 char *d;
706
707 if (!*args[1]) {
708 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
709 file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713
714 for(i=1; *args[i]; i++)
715 len += strlen(args[i])+1;
716
717 if (global.desc)
718 free(global.desc);
719
720 global.desc = d = (char *)calloc(1, len);
721
722 d += sprintf(d, "%s", args[1]);
723 for(i=2; *args[i]; i++)
724 d += sprintf(d, " %s", args[i]);
725 }
726 else if (!strcmp(args[0], "node")) {
727 int i;
728 char c;
729
730 for (i=0; args[1][i]; i++) {
731 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100732 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
733 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200734 break;
735 }
736
737 if (!i || args[1][i]) {
738 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
739 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
740 file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744
745 if (global.node)
746 free(global.node);
747
748 global.node = strdup(args[1]);
749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 else if (!strcmp(args[0], "pidfile")) {
751 if (global.pidfile != NULL) {
752 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 err_code |= ERR_ALERT;
754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200755 }
756 if (*(args[1]) == 0) {
757 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 }
761 global.pidfile = strdup(args[1]);
762 }
763 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100764 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200765 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766
767 if (*(args[1]) == 0 || *(args[2]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772
773 facility = get_log_facility(args[2]);
774 if (facility < 0) {
775 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200776 err_code |= ERR_ALERT | ERR_FATAL;
777 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 }
779
780 level = 7; /* max syslog level = debug */
781 if (*(args[3])) {
782 level = get_log_level(args[3]);
783 if (level < 0) {
784 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT | ERR_FATAL;
786 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 }
788 }
789
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200790 minlvl = 0; /* limit syslog level to this level (emerg) */
791 if (*(args[4])) {
792 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200793 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200794 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 err_code |= ERR_ALERT | ERR_FATAL;
796 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200797 }
798 }
799
Robert Tsai81ae1952007-12-05 10:47:29 +0100800 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100801 struct sockaddr_un *sk = str2sun(args[1]);
802 if (!sk) {
803 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
804 args[1], (int)sizeof(sk->sun_path) - 1);
805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
807 }
808 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100809 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100810 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100811 struct sockaddr_in *sk = str2sa(args[1]);
812 if (!sk) {
813 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100818 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100819 if (!logsrv.u.in.sin_port)
820 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
821 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822
823 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100824 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200825 global.logfac1 = facility;
826 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200827 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 }
829 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100830 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200831 global.logfac2 = facility;
832 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200833 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 else {
836 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200839 }
840 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
841 if (global.spread_checks != 0) {
842 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT;
844 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200845 }
846 if (*(args[1]) == 0) {
847 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200848 err_code |= ERR_ALERT | ERR_FATAL;
849 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200850 }
851 global.spread_checks = atol(args[1]);
852 if (global.spread_checks < 0 || global.spread_checks > 50) {
853 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200854 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 }
857 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200858 struct cfg_kw_list *kwl;
859 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200860 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200861
862 list_for_each_entry(kwl, &cfg_keywords.list, list) {
863 for (index = 0; kwl->kw[index].kw != NULL; index++) {
864 if (kwl->kw[index].section != CFG_GLOBAL)
865 continue;
866 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
867 /* prepare error message just in case */
868 snprintf(trash, sizeof(trash),
869 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200870 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
871 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200872 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200873 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200874 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200875 else if (rc > 0) {
876 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_WARN;
878 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200879 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200880 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200881 }
882 }
883 }
884
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200888
Willy Tarreau058e9072009-07-20 09:30:05 +0200889 out:
890 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891}
892
Willy Tarreau97cb7802010-01-03 20:23:58 +0100893/* Perform the most basic initialization of a proxy :
894 * memset(), list_init(*), reset_timeouts(*).
895 */
896static void init_new_proxy(struct proxy *p)
897{
898 memset(p, 0, sizeof(struct proxy));
899 LIST_INIT(&p->pendconns);
900 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100901 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100902 LIST_INIT(&p->block_cond);
903 LIST_INIT(&p->redirect_rules);
904 LIST_INIT(&p->mon_fail_cond);
905 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +0200906 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100907 LIST_INIT(&p->sticking_rules);
908 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100909 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100910 LIST_INIT(&p->req_add);
911 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100912
913 /* Timeouts are defined as -1 */
914 proxy_reset_timeouts(p);
915}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200917void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100919 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 defproxy.mode = PR_MODE_TCP;
921 defproxy.state = PR_STNEW;
922 defproxy.maxconn = cfg_maxpconn;
923 defproxy.conn_retries = CONN_RETRIES;
924 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100925
926 defproxy.defsrv.inter = DEF_CHKINTR;
927 defproxy.defsrv.fastinter = 0;
928 defproxy.defsrv.downinter = 0;
929 defproxy.defsrv.rise = DEF_RISETIME;
930 defproxy.defsrv.fall = DEF_FALLTIME;
931 defproxy.defsrv.check_port = 0;
932 defproxy.defsrv.maxqueue = 0;
933 defproxy.defsrv.minconn = 0;
934 defproxy.defsrv.maxconn = 0;
935 defproxy.defsrv.slowstart = 0;
936 defproxy.defsrv.onerror = DEF_HANA_ONERR;
937 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
938 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939}
940
Willy Tarreauade5ec42010-01-28 19:33:49 +0100941
942static int create_cond_regex_rule(const char *file, int line,
943 struct proxy *px, int dir, int action, int flags,
944 const char *cmd, const char *reg, const char *repl,
945 const char **cond_start)
946{
947 regex_t *preg = NULL;
948 const char *err;
949 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100950 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100951
952 if (px == &defproxy) {
953 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto err;
956 }
957
958 if (*reg == 0) {
959 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto err;
962 }
963
964 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
965 err_code |= ERR_WARN;
966
Willy Tarreau5321c422010-01-28 20:35:13 +0100967 if (cond_start &&
968 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
969 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
970 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
971 file, line, cmd);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto err;
974 }
975 }
976 else if (cond_start && **cond_start) {
977 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
978 file, line, cmd, *cond_start);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto err;
981 }
982
983 if (dir == ACL_DIR_REQ)
984 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100985 else
986 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100987
Willy Tarreauade5ec42010-01-28 19:33:49 +0100988 preg = calloc(1, sizeof(regex_t));
989 if (!preg) {
990 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
991 err_code = ERR_ALERT | ERR_FATAL;
992 goto err;
993 }
994
995 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
996 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
997 err_code = ERR_ALERT | ERR_FATAL;
998 goto err;
999 }
1000
1001 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001002 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001003 if (repl && err) {
1004 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1005 file, line, cmd, *err);
1006 err_code |= ERR_ALERT | ERR_FATAL;
1007 goto err;
1008 }
1009
1010 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1011 err_code |= ERR_WARN;
1012
1013 return err_code;
1014 err:
1015 free(preg);
1016 return err_code;
1017}
1018
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001020 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001021 * Returns the error code, 0 if OK, or any combination of :
1022 * - ERR_ABORT: must abort ASAP
1023 * - ERR_FATAL: we can continue parsing but not start the service
1024 * - ERR_WARN: a warning has been emitted
1025 * - ERR_ALERT: an alert has been emitted
1026 * Only the two first ones can stop processing, the two others are just
1027 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001029int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030{
1031 static struct proxy *curproxy = NULL;
1032 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001033 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001034 int rc;
1035 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001036 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001037 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038
Willy Tarreau977b8e42006-12-29 14:19:17 +01001039 if (!strcmp(args[0], "listen"))
1040 rc = PR_CAP_LISTEN;
1041 else if (!strcmp(args[0], "frontend"))
1042 rc = PR_CAP_FE | PR_CAP_RS;
1043 else if (!strcmp(args[0], "backend"))
1044 rc = PR_CAP_BE | PR_CAP_RS;
1045 else if (!strcmp(args[0], "ruleset"))
1046 rc = PR_CAP_RS;
1047 else
1048 rc = PR_CAP_NONE;
1049
1050 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 if (!*args[1]) {
1052 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1053 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1054 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001055 err_code |= ERR_ALERT | ERR_ABORT;
1056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001058
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001059 err = invalid_char(args[1]);
1060 if (err) {
1061 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1062 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001063 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001064 }
1065
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001066 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1067 /*
1068 * If there are two proxies with the same name only following
1069 * combinations are allowed:
1070 *
1071 * listen backend frontend ruleset
1072 * listen - - - -
1073 * backend - - OK -
1074 * frontend - OK - -
1075 * ruleset - - - -
1076 */
1077
1078 if (!strcmp(curproxy->id, args[1]) &&
1079 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1080 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001081 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1082 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1083 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001084 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001085 }
1086 }
1087
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001090 err_code |= ERR_ALERT | ERR_ABORT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001093
Willy Tarreau97cb7802010-01-03 20:23:58 +01001094 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 curproxy->next = proxy;
1096 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001097 curproxy->conf.file = file;
1098 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001099 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001101 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102
1103 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001104 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001105 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001106 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001107 err_code |= ERR_FATAL;
1108 goto out;
1109 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001110 new = curproxy->listen;
1111 while (new != last) {
1112 new->conf.file = file;
1113 new->conf.line = linenum;
1114 new = new->next;
1115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 global.maxsock++;
1117 }
1118
1119 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001120 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001121 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001122
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001125 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001126 curproxy->no_options = defproxy.no_options;
1127 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001128 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001129 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001130 curproxy->except_net = defproxy.except_net;
1131 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001132 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001133 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001135 if (defproxy.fwdfor_hdr_len) {
1136 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1137 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1138 }
1139
Willy Tarreaub86db342009-11-30 11:50:16 +01001140 if (defproxy.orgto_hdr_len) {
1141 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1142 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1143 }
1144
Willy Tarreau977b8e42006-12-29 14:19:17 +01001145 if (curproxy->cap & PR_CAP_FE) {
1146 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001147 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001148 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001149
1150 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001151 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1152 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001153
1154 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156
Willy Tarreau977b8e42006-12-29 14:19:17 +01001157 if (curproxy->cap & PR_CAP_BE) {
1158 curproxy->fullconn = defproxy.fullconn;
1159 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160
Willy Tarreau977b8e42006-12-29 14:19:17 +01001161 if (defproxy.check_req)
1162 curproxy->check_req = strdup(defproxy.check_req);
1163 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164
Willy Tarreau977b8e42006-12-29 14:19:17 +01001165 if (defproxy.cookie_name)
1166 curproxy->cookie_name = strdup(defproxy.cookie_name);
1167 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001168 if (defproxy.cookie_domain)
1169 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001170
Emeric Brun647caf12009-06-30 17:57:00 +02001171 if (defproxy.rdp_cookie_name)
1172 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1173 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1174
Willy Tarreau01732802007-11-01 22:48:15 +01001175 if (defproxy.url_param_name)
1176 curproxy->url_param_name = strdup(defproxy.url_param_name);
1177 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001178
Benoitaffb4812009-03-25 13:02:10 +01001179 if (defproxy.hh_name)
1180 curproxy->hh_name = strdup(defproxy.hh_name);
1181 curproxy->hh_len = defproxy.hh_len;
1182 curproxy->hh_match_domain = defproxy.hh_match_domain;
1183
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001184 if (defproxy.iface_name)
1185 curproxy->iface_name = strdup(defproxy.iface_name);
1186 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001188
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001189 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001190 if (defproxy.capture_name)
1191 curproxy->capture_name = strdup(defproxy.capture_name);
1192 curproxy->capture_namelen = defproxy.capture_namelen;
1193 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195
Willy Tarreau977b8e42006-12-29 14:19:17 +01001196 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001197 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001198 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001199 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001200 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001201 curproxy->uri_auth = defproxy.uri_auth;
1202 curproxy->mon_net = defproxy.mon_net;
1203 curproxy->mon_mask = defproxy.mon_mask;
1204 if (defproxy.monitor_uri)
1205 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1206 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001207 if (defproxy.defbe.name)
1208 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001209 }
1210
1211 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001212 curproxy->timeout.connect = defproxy.timeout.connect;
1213 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001214 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001215 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001216 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001217 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001218 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001219 curproxy->source_addr = defproxy.source_addr;
1220 }
1221
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 curproxy->mode = defproxy.mode;
1223 curproxy->logfac1 = defproxy.logfac1;
1224 curproxy->logsrv1 = defproxy.logsrv1;
1225 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001226 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227 curproxy->logfac2 = defproxy.logfac2;
1228 curproxy->logsrv2 = defproxy.logsrv2;
1229 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001230 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001232 curproxy->conf.used_listener_id = EB_ROOT;
1233 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001234
Willy Tarreau93893792009-07-23 13:19:11 +02001235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 }
1237 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1238 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001239 /* FIXME-20070101: we should do this too at the end of the
1240 * config parsing to free all default values.
1241 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001242 free(defproxy.check_req);
1243 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001244 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001245 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001246 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001247 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001248 free(defproxy.capture_name);
1249 free(defproxy.monitor_uri);
1250 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001251 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001252 free(defproxy.fwdfor_hdr_name);
1253 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001254 free(defproxy.orgto_hdr_name);
1255 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001256
Willy Tarreaua534fea2008-08-03 12:19:50 +02001257 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001258 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001259
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 /* we cannot free uri_auth because it might already be used */
1261 init_default_instance();
1262 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001263 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001265 }
1266 else if (curproxy == NULL) {
1267 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 }
1271
Willy Tarreau977b8e42006-12-29 14:19:17 +01001272
1273 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001275 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001276 int cur_arg;
1277
Willy Tarreaubaaee002006-06-26 02:48:02 +02001278 if (curproxy == &defproxy) {
1279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001283 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001284 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285
1286 if (strchr(args[1], ':') == NULL) {
1287 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001289 err_code |= ERR_ALERT | ERR_FATAL;
1290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001292
1293 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001294 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001298
Willy Tarreau90a570f2009-10-04 20:54:54 +02001299 new_listen = curproxy->listen;
1300 while (new_listen != last_listen) {
1301 new_listen->conf.file = file;
1302 new_listen->conf.line = linenum;
1303 new_listen = new_listen->next;
1304 }
1305
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001306 cur_arg = 2;
1307 while (*(args[cur_arg])) {
1308 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1309#ifdef SO_BINDTODEVICE
1310 struct listener *l;
1311
1312 if (!*args[cur_arg + 1]) {
1313 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1314 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001317 }
1318
1319 for (l = curproxy->listen; l != last_listen; l = l->next)
1320 l->interface = strdup(args[cur_arg + 1]);
1321
1322 global.last_checks |= LSTCHK_NETADM;
1323
1324 cur_arg += 2;
1325 continue;
1326#else
1327 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1328 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001331#endif
1332 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001333 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1334#ifdef TCP_MAXSEG
1335 struct listener *l;
1336 int mss;
1337
1338 if (!*args[cur_arg + 1]) {
1339 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001343 }
1344
1345 mss = str2uic(args[cur_arg + 1]);
1346 if (mss < 1 || mss > 65535) {
1347 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001349 err_code |= ERR_ALERT | ERR_FATAL;
1350 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001351 }
1352
1353 for (l = curproxy->listen; l != last_listen; l = l->next)
1354 l->maxseg = mss;
1355
1356 cur_arg += 2;
1357 continue;
1358#else
1359 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1360 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001363#endif
1364 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001365
1366 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1367#ifdef TCP_DEFER_ACCEPT
1368 struct listener *l;
1369
1370 for (l = curproxy->listen; l != last_listen; l = l->next)
1371 l->options |= LI_O_DEF_ACCEPT;
1372
1373 cur_arg ++;
1374 continue;
1375#else
1376 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1377 file, linenum, args[0], args[cur_arg]);
1378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto out;
1380#endif
1381 }
1382
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001383 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001384#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001385 struct listener *l;
1386
1387 for (l = curproxy->listen; l != last_listen; l = l->next)
1388 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001389
1390 cur_arg ++;
1391 continue;
1392#else
1393 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1394 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001397#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001398 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001399
1400 if (!strcmp(args[cur_arg], "name")) {
1401 struct listener *l;
1402
1403 for (l = curproxy->listen; l != last_listen; l = l->next)
1404 l->name = strdup(args[cur_arg + 1]);
1405
1406 cur_arg += 2;
1407 continue;
1408 }
1409
1410 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001411 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001412 struct listener *l;
1413
1414 if (curproxy->listen->next != last_listen) {
1415 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1416 file, linenum, args[cur_arg]);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
1421 if (!*args[cur_arg + 1]) {
1422 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1423 file, linenum, args[cur_arg]);
1424 err_code |= ERR_ALERT | ERR_FATAL;
1425 goto out;
1426 }
1427
1428 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001429 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001430
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001431 if (curproxy->listen->luid <= 0) {
1432 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001433 file, linenum);
1434 err_code |= ERR_ALERT | ERR_FATAL;
1435 goto out;
1436 }
1437
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001438 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1439 if (node) {
1440 l = container_of(node, struct listener, conf.id);
1441 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1442 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1447
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001448 cur_arg += 2;
1449 continue;
1450 }
1451
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001452 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001453 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 }
1460 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1461 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1462 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001467 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001468 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 /* flush useless bits */
1471 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001474 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001475 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001476 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001477
Willy Tarreau1c47f852006-07-09 08:22:27 +02001478 if (!*args[1]) {
1479 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001483 }
1484
Willy Tarreaua534fea2008-08-03 12:19:50 +02001485 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001486 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001487 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001488 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001489 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1490
Willy Tarreau93893792009-07-23 13:19:11 +02001491 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1494 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1495 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1496 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1497 else {
1498 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 }
1502 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001503 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001504 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001505
1506 if (curproxy == &defproxy) {
1507 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1508 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001511 }
1512
1513 if (!*args[1]) {
1514 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1515 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001518 }
1519
1520 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001521 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001522
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001523 if (curproxy->uuid <= 0) {
1524 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001525 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001526 err_code |= ERR_ALERT | ERR_FATAL;
1527 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001528 }
1529
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001530 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1531 if (node) {
1532 struct proxy *target = container_of(node, struct proxy, conf.id);
1533 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1534 file, linenum, proxy_type_str(curproxy), curproxy->id,
1535 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001540 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001541 else if (!strcmp(args[0], "description")) {
1542 int i, len=0;
1543 char *d;
1544
Cyril Bonté99ed3272010-01-24 23:29:44 +01001545 if (curproxy == &defproxy) {
1546 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1547 file, linenum, args[0]);
1548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
1550 }
1551
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001552 if (!*args[1]) {
1553 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1554 file, linenum, args[0]);
1555 return -1;
1556 }
1557
1558 for(i=1; *args[i]; i++)
1559 len += strlen(args[i])+1;
1560
1561 d = (char *)calloc(1, len);
1562 curproxy->desc = d;
1563
1564 d += sprintf(d, "%s", args[1]);
1565 for(i=2; *args[i]; i++)
1566 d += sprintf(d, " %s", args[i]);
1567
1568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1570 curproxy->state = PR_STSTOPPED;
1571 }
1572 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1573 curproxy->state = PR_STNEW;
1574 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001575 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1576 int cur_arg = 1;
1577 unsigned int set = 0;
1578
1579 while (*args[cur_arg]) {
1580 int u;
1581 if (strcmp(args[cur_arg], "all") == 0) {
1582 set = 0;
1583 break;
1584 }
1585 else if (strcmp(args[cur_arg], "odd") == 0) {
1586 set |= 0x55555555;
1587 }
1588 else if (strcmp(args[cur_arg], "even") == 0) {
1589 set |= 0xAAAAAAAA;
1590 }
1591 else {
1592 u = str2uic(args[cur_arg]);
1593 if (u < 1 || u > 32) {
1594 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001598 }
1599 if (u > global.nbproc) {
1600 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1601 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001602 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001603 }
1604 set |= 1 << (u - 1);
1605 }
1606 cur_arg++;
1607 }
1608 curproxy->bind_proc = set;
1609 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001610 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001611 if (curproxy == &defproxy) {
1612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001613 err_code |= ERR_ALERT | ERR_FATAL;
1614 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001615 }
1616
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001617 err = invalid_char(args[1]);
1618 if (err) {
1619 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1620 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001621 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001622 }
1623
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001624 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1625 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1626 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001629 }
1630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1632 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633
Willy Tarreau977b8e42006-12-29 14:19:17 +01001634 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001636
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 if (*(args[1]) == 0) {
1638 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1639 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001640 err_code |= ERR_ALERT | ERR_FATAL;
1641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001643
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001644 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001645 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 curproxy->cookie_name = strdup(args[1]);
1647 curproxy->cookie_len = strlen(curproxy->cookie_name);
1648
1649 cur_arg = 2;
1650 while (*(args[cur_arg])) {
1651 if (!strcmp(args[cur_arg], "rewrite")) {
1652 curproxy->options |= PR_O_COOK_RW;
1653 }
1654 else if (!strcmp(args[cur_arg], "indirect")) {
1655 curproxy->options |= PR_O_COOK_IND;
1656 }
1657 else if (!strcmp(args[cur_arg], "insert")) {
1658 curproxy->options |= PR_O_COOK_INS;
1659 }
1660 else if (!strcmp(args[cur_arg], "nocache")) {
1661 curproxy->options |= PR_O_COOK_NOC;
1662 }
1663 else if (!strcmp(args[cur_arg], "postonly")) {
1664 curproxy->options |= PR_O_COOK_POST;
1665 }
1666 else if (!strcmp(args[cur_arg], "prefix")) {
1667 curproxy->options |= PR_O_COOK_PFX;
1668 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001669 else if (!strcmp(args[cur_arg], "domain")) {
1670 if (!*args[cur_arg + 1]) {
1671 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1672 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
1674 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001675 }
1676
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001677 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001678 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001679 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1680 " dots nor does not start with a dot."
1681 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001682 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001683 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001684 }
1685
1686 err = invalid_domainchar(args[cur_arg + 1]);
1687 if (err) {
1688 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1689 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001692 }
1693
Willy Tarreau68a897b2009-12-03 23:28:34 +01001694 if (!curproxy->cookie_domain) {
1695 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1696 } else {
1697 /* one domain was already specified, add another one by
1698 * building the string which will be returned along with
1699 * the cookie.
1700 */
1701 char *new_ptr;
1702 int new_len = strlen(curproxy->cookie_domain) +
1703 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1704 new_ptr = malloc(new_len);
1705 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1706 free(curproxy->cookie_domain);
1707 curproxy->cookie_domain = new_ptr;
1708 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001709 cur_arg++;
1710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001712 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001714 err_code |= ERR_ALERT | ERR_FATAL;
1715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 }
1717 cur_arg++;
1718 }
1719 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1720 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1721 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 }
1724
1725 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1726 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1727 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 }
1730 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001731 else if (!strcmp(args[0], "persist")) { /* persist */
1732 if (*(args[1]) == 0) {
1733 Alert("parsing [%s:%d] : missing persist method.\n",
1734 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001737 }
1738
1739 if (!strncmp(args[1], "rdp-cookie", 10)) {
1740 curproxy->options2 |= PR_O2_RDPC_PRST;
1741
Emeric Brunb982a3d2010-01-04 15:45:53 +01001742 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001743 const char *beg, *end;
1744
1745 beg = args[1] + 11;
1746 end = strchr(beg, ')');
1747
1748 if (!end || end == beg) {
1749 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1750 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001751 err_code |= ERR_ALERT | ERR_FATAL;
1752 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001753 }
1754
1755 free(curproxy->rdp_cookie_name);
1756 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1757 curproxy->rdp_cookie_len = end-beg;
1758 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001759 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001760 free(curproxy->rdp_cookie_name);
1761 curproxy->rdp_cookie_name = strdup("msts");
1762 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1763 }
1764 else { /* syntax */
1765 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1766 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001769 }
1770 }
1771 else {
1772 Alert("parsing [%s:%d] : unknown persist method.\n",
1773 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001776 }
1777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001779 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001781 if (curproxy == &defproxy) {
1782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
1785 }
1786
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001791 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 }
1796 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001797 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798 curproxy->appsession_name = strdup(args[1]);
1799 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1800 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001801 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1802 if (err) {
1803 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1804 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001807 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001808 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001809
Willy Tarreau51041c72007-09-09 21:56:53 +02001810 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1811 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001812 err_code |= ERR_ALERT | ERR_ABORT;
1813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001814 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001815
1816 cur_arg = 6;
1817 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001818 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1819 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001820 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001821 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001822 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001823 } else if (!strcmp(args[cur_arg], "prefix")) {
1824 curproxy->options2 |= PR_O2_AS_PFX;
1825 } else if (!strcmp(args[cur_arg], "mode")) {
1826 if (!*args[cur_arg + 1]) {
1827 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1828 file, linenum, args[0], args[cur_arg]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831 }
1832
1833 cur_arg++;
1834 if (!strcmp(args[cur_arg], "query-string")) {
1835 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1836 curproxy->options2 |= PR_O2_AS_M_QS;
1837 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1838 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1839 curproxy->options2 |= PR_O2_AS_M_PP;
1840 } else {
1841 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
1845 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001846 cur_arg++;
1847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 } /* Url App Session */
1849 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001850 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001852
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001854 if (curproxy == &defproxy) {
1855 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1856 err_code |= ERR_ALERT | ERR_FATAL;
1857 goto out;
1858 }
1859
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 if (*(args[4]) == 0) {
1861 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1862 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001863 err_code |= ERR_ALERT | ERR_FATAL;
1864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001866 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001867 curproxy->capture_name = strdup(args[2]);
1868 curproxy->capture_namelen = strlen(curproxy->capture_name);
1869 curproxy->capture_len = atol(args[4]);
1870 if (curproxy->capture_len >= CAPTURE_LEN) {
1871 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1872 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001873 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 curproxy->capture_len = CAPTURE_LEN - 1;
1875 }
1876 curproxy->to_log |= LW_COOKIE;
1877 }
1878 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1879 struct cap_hdr *hdr;
1880
1881 if (curproxy == &defproxy) {
1882 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 +02001883 err_code |= ERR_ALERT | ERR_FATAL;
1884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 }
1886
1887 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1888 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1889 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 }
1893
1894 hdr = calloc(sizeof(struct cap_hdr), 1);
1895 hdr->next = curproxy->req_cap;
1896 hdr->name = strdup(args[3]);
1897 hdr->namelen = strlen(args[3]);
1898 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001899 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 hdr->index = curproxy->nb_req_cap++;
1901 curproxy->req_cap = hdr;
1902 curproxy->to_log |= LW_REQHDR;
1903 }
1904 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1905 struct cap_hdr *hdr;
1906
1907 if (curproxy == &defproxy) {
1908 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 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 }
1912
1913 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1914 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1915 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001916 err_code |= ERR_ALERT | ERR_FATAL;
1917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 }
1919 hdr = calloc(sizeof(struct cap_hdr), 1);
1920 hdr->next = curproxy->rsp_cap;
1921 hdr->name = strdup(args[3]);
1922 hdr->namelen = strlen(args[3]);
1923 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001924 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 hdr->index = curproxy->nb_rsp_cap++;
1926 curproxy->rsp_cap = hdr;
1927 curproxy->to_log |= LW_RSPHDR;
1928 }
1929 else {
1930 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 }
1935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001937 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 if (*(args[1]) == 0) {
1941 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_ALERT | ERR_FATAL;
1944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 }
1946 curproxy->conn_retries = atol(args[1]);
1947 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001948 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1949 struct req_acl_rule *req_acl;
1950
1951 if (curproxy == &defproxy) {
1952 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
1955 }
1956
1957
1958 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1959 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1960 file, linenum, args[0]);
1961 err_code |= ERR_WARN;
1962 }
1963
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001964 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001965
1966 if (!req_acl) {
1967 err_code |= ERR_ALERT | ERR_ABORT;
1968 goto out;
1969 }
1970
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001971 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001972 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1973 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001974 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001975 if (curproxy == &defproxy) {
1976 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001977 err_code |= ERR_ALERT | ERR_FATAL;
1978 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001979 }
1980
Willy Tarreauef6494c2010-01-28 17:12:36 +01001981 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001982 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1983 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001986 }
1987
Willy Tarreauef6494c2010-01-28 17:12:36 +01001988 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001989 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1990 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001993 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001994
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001995 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001996 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001997 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001998 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001999 struct redirect_rule *rule;
2000 int cur_arg;
2001 int type = REDIRECT_TYPE_NONE;
2002 int code = 302;
2003 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002004 char *cookie = NULL;
2005 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002006 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002007
Cyril Bonté99ed3272010-01-24 23:29:44 +01002008 if (curproxy == &defproxy) {
2009 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
2013
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002014 cur_arg = 1;
2015 while (*(args[cur_arg])) {
2016 if (!strcmp(args[cur_arg], "location")) {
2017 if (!*args[cur_arg + 1]) {
2018 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2019 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002022 }
2023
2024 type = REDIRECT_TYPE_LOCATION;
2025 cur_arg++;
2026 destination = args[cur_arg];
2027 }
2028 else if (!strcmp(args[cur_arg], "prefix")) {
2029 if (!*args[cur_arg + 1]) {
2030 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2031 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002034 }
2035
2036 type = REDIRECT_TYPE_PREFIX;
2037 cur_arg++;
2038 destination = args[cur_arg];
2039 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002040 else if (!strcmp(args[cur_arg], "set-cookie")) {
2041 if (!*args[cur_arg + 1]) {
2042 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2043 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002046 }
2047
2048 cur_arg++;
2049 cookie = args[cur_arg];
2050 cookie_set = 1;
2051 }
2052 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2053 if (!*args[cur_arg + 1]) {
2054 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2055 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002058 }
2059
2060 cur_arg++;
2061 cookie = args[cur_arg];
2062 cookie_set = 0;
2063 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002064 else if (!strcmp(args[cur_arg],"code")) {
2065 if (!*args[cur_arg + 1]) {
2066 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002070 }
2071 cur_arg++;
2072 code = atol(args[cur_arg]);
2073 if (code < 301 || code > 303) {
2074 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2075 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002078 }
2079 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002080 else if (!strcmp(args[cur_arg],"drop-query")) {
2081 flags |= REDIRECT_FLAG_DROP_QS;
2082 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002083 else if (!strcmp(args[cur_arg],"append-slash")) {
2084 flags |= REDIRECT_FLAG_APPEND_SLASH;
2085 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002086 else if (strcmp(args[cur_arg], "if") == 0 ||
2087 strcmp(args[cur_arg], "unless") == 0) {
2088 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2089 if (!cond) {
2090 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2091 file, linenum, args[0]);
2092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
2094 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002095 break;
2096 }
2097 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002098 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 +02002099 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002102 }
2103 cur_arg++;
2104 }
2105
2106 if (type == REDIRECT_TYPE_NONE) {
2107 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2108 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002111 }
2112
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002113 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2114 rule->cond = cond;
2115 rule->rdr_str = strdup(destination);
2116 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002117 if (cookie) {
2118 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002119 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002120 */
2121 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002122 if (cookie_set) {
2123 rule->cookie_str = malloc(rule->cookie_len + 10);
2124 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2125 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2126 rule->cookie_len += 9;
2127 } else {
2128 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002129 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002130 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2131 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002132 }
2133 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002134 rule->type = type;
2135 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002136 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002137 LIST_INIT(&rule->list);
2138 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002139 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002140 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002141 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002142 struct switching_rule *rule;
2143
Willy Tarreaub099aca2008-10-12 17:26:37 +02002144 if (curproxy == &defproxy) {
2145 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002148 }
2149
Willy Tarreau55ea7572007-06-17 19:56:27 +02002150 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002151 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002152
2153 if (*(args[1]) == 0) {
2154 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002157 }
2158
Willy Tarreauef6494c2010-01-28 17:12:36 +01002159 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002160 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2161 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002164 }
2165
Willy Tarreauef6494c2010-01-28 17:12:36 +01002166 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002167 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002168 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002171 }
2172
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002173 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002174
Willy Tarreau55ea7572007-06-17 19:56:27 +02002175 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2176 rule->cond = cond;
2177 rule->be.name = strdup(args[1]);
2178 LIST_INIT(&rule->list);
2179 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2180 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002181 else if ((!strcmp(args[0], "force-persist")) ||
2182 (!strcmp(args[0], "ignore-persist"))) {
2183 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002184
2185 if (curproxy == &defproxy) {
2186 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190
2191 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2192 err_code |= ERR_WARN;
2193
Willy Tarreauef6494c2010-01-28 17:12:36 +01002194 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002195 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2196 file, linenum, args[0]);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
Willy Tarreauef6494c2010-01-28 17:12:36 +01002201 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002202 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2203 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
2206 }
2207
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002208 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002209
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002210 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002211 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002212 if (!strcmp(args[0], "force-persist")) {
2213 rule->type = PERSIST_TYPE_FORCE;
2214 } else {
2215 rule->type = PERSIST_TYPE_IGNORE;
2216 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002217 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002218 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002219 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002220 else if (!strcmp(args[0], "stick-table")) {
2221 int myidx = 1;
2222
2223 curproxy->table.type = (unsigned int)-1;
2224 while (*args[myidx]) {
2225 const char *err;
2226
2227 if (strcmp(args[myidx], "size") == 0) {
2228 myidx++;
2229 if (!*(args[myidx])) {
2230 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2231 file, linenum, args[myidx-1]);
2232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
2234 }
2235 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2236 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2237 file, linenum, *err, args[myidx-1]);
2238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
2240 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002241 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002242 }
2243 else if (strcmp(args[myidx], "expire") == 0) {
2244 myidx++;
2245 if (!*(args[myidx])) {
2246 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2247 file, linenum, args[myidx-1]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2252 if (err) {
2253 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2254 file, linenum, *err, args[myidx-1]);
2255 err_code |= ERR_ALERT | ERR_FATAL;
2256 goto out;
2257 }
2258 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002259 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002260 }
2261 else if (strcmp(args[myidx], "nopurge") == 0) {
2262 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002263 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002264 }
2265 else if (strcmp(args[myidx], "type") == 0) {
2266 myidx++;
2267 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2268 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2269 file, linenum, args[myidx]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002273 /* myidx already points to next arg */
2274 }
2275 else {
2276 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2277 file, linenum, args[myidx]);
2278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002280 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002281 }
2282
2283 if (!curproxy->table.size) {
2284 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2285 file, linenum);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289
2290 if (curproxy->table.type == (unsigned int)-1) {
2291 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2292 file, linenum);
2293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
2295 }
2296 }
2297 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002298 struct sticking_rule *rule;
2299 struct pattern_expr *expr;
2300 int myidx = 0;
2301 const char *name = NULL;
2302 int flags;
2303
2304 if (curproxy == &defproxy) {
2305 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2311 err_code |= ERR_WARN;
2312 goto out;
2313 }
2314
2315 myidx++;
2316 if ((strcmp(args[myidx], "store") == 0) ||
2317 (strcmp(args[myidx], "store-request") == 0)) {
2318 myidx++;
2319 flags = STK_IS_STORE;
2320 }
2321 else if (strcmp(args[myidx], "store-response") == 0) {
2322 myidx++;
2323 flags = STK_IS_STORE | STK_ON_RSP;
2324 }
2325 else if (strcmp(args[myidx], "match") == 0) {
2326 myidx++;
2327 flags = STK_IS_MATCH;
2328 }
2329 else if (strcmp(args[myidx], "on") == 0) {
2330 myidx++;
2331 flags = STK_IS_MATCH | STK_IS_STORE;
2332 }
2333 else {
2334 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338
2339 if (*(args[myidx]) == 0) {
2340 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
2343 }
2344
2345 expr = pattern_parse_expr(args, &myidx);
2346 if (!expr) {
2347 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351
2352 if (flags & STK_ON_RSP) {
2353 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2354 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2355 file, linenum, args[0], expr->fetch->kw);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
2358 }
2359 } else {
2360 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2361 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2362 file, linenum, args[0], expr->fetch->kw);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366 }
2367
2368 if (strcmp(args[myidx], "table") == 0) {
2369 myidx++;
2370 name = args[myidx++];
2371 }
2372
Willy Tarreauef6494c2010-01-28 17:12:36 +01002373 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2374 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002375 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2376 file, linenum, args[0]);
2377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
2379 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002380 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002381 else if (*(args[myidx])) {
2382 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2383 file, linenum, args[0], args[myidx]);
2384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
2386 }
2387
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002388 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2389
Emeric Brunb982a3d2010-01-04 15:45:53 +01002390 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2391 rule->cond = cond;
2392 rule->expr = expr;
2393 rule->flags = flags;
2394 rule->table.name = name ? strdup(name) : NULL;
2395 LIST_INIT(&rule->list);
2396 if (flags & STK_ON_RSP)
2397 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2398 else
2399 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002402 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2406 curproxy->uri_auth = NULL; /* we must detach from the default config */
2407
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002408 if (!*args[1]) {
2409 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 } else if (!strcmp(args[1], "uri")) {
2411 if (*(args[2]) == 0) {
2412 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_ABORT;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420 } else if (!strcmp(args[1], "realm")) {
2421 if (*(args[2]) == 0) {
2422 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2426 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_ABORT;
2428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002430 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002431 unsigned interval;
2432
2433 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2434 if (err) {
2435 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2436 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002439 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2440 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002441 err_code |= ERR_ALERT | ERR_ABORT;
2442 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002443 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002444 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2445 struct req_acl_rule *req_acl;
2446
2447 if (curproxy == &defproxy) {
2448 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452
2453 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2454 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2455 err_code |= ERR_ALERT | ERR_ABORT;
2456 goto out;
2457 }
2458
2459 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2460 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2461 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2462 file, linenum, args[0]);
2463 err_code |= ERR_WARN;
2464 }
2465
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002466 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002467
2468 if (!req_acl) {
2469 err_code |= ERR_ALERT | ERR_ABORT;
2470 goto out;
2471 }
2472
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002473 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002474 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2475
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 } else if (!strcmp(args[1], "auth")) {
2477 if (*(args[2]) == 0) {
2478 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2482 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_ABORT;
2484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
2486 } else if (!strcmp(args[1], "scope")) {
2487 if (*(args[2]) == 0) {
2488 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2492 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_ABORT;
2494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 }
2496 } else if (!strcmp(args[1], "enable")) {
2497 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2498 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_ABORT;
2500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002502 } else if (!strcmp(args[1], "hide-version")) {
2503 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2504 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_ABORT;
2506 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002507 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002508 } else if (!strcmp(args[1], "show-legends")) {
2509 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2510 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2511 err_code |= ERR_ALERT | ERR_ABORT;
2512 goto out;
2513 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002514 } else if (!strcmp(args[1], "show-node")) {
2515
2516 if (*args[2]) {
2517 int i;
2518 char c;
2519
2520 for (i=0; args[2][i]; i++) {
2521 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002522 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2523 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002524 break;
2525 }
2526
2527 if (!i || args[2][i]) {
2528 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2529 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2530 file, linenum, args[0], args[1]);
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534 }
2535
2536 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2537 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2538 err_code |= ERR_ALERT | ERR_ABORT;
2539 goto out;
2540 }
2541 } else if (!strcmp(args[1], "show-desc")) {
2542 char *desc = NULL;
2543
2544 if (*args[2]) {
2545 int i, len=0;
2546 char *d;
2547
2548 for(i=2; *args[i]; i++)
2549 len += strlen(args[i])+1;
2550
2551 desc = d = (char *)calloc(1, len);
2552
2553 d += sprintf(d, "%s", args[2]);
2554 for(i=3; *args[i]; i++)
2555 d += sprintf(d, " %s", args[i]);
2556 }
2557
2558 if (!*args[2] && !global.desc)
2559 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2560 file, linenum, args[1]);
2561 else {
2562 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2563 free(desc);
2564 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2565 err_code |= ERR_ALERT | ERR_ABORT;
2566 goto out;
2567 }
2568 free(desc);
2569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002571stats_error_parsing:
2572 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2573 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577 }
2578 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002579 int optnum;
2580
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002581 if (*(args[1]) == '\0') {
2582 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002587
2588 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2589 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002590 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2591 err_code |= ERR_WARN;
2592 goto out;
2593 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002594
Willy Tarreau3842f002009-06-14 11:39:52 +02002595 curproxy->no_options &= ~cfg_opts[optnum].val;
2596 curproxy->options &= ~cfg_opts[optnum].val;
2597
2598 switch (kwm) {
2599 case KWM_STD:
2600 curproxy->options |= cfg_opts[optnum].val;
2601 break;
2602 case KWM_NO:
2603 curproxy->no_options |= cfg_opts[optnum].val;
2604 break;
2605 case KWM_DEF: /* already cleared */
2606 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002607 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002608
Willy Tarreau93893792009-07-23 13:19:11 +02002609 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002610 }
2611 }
2612
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002613 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2614 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002615 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2616 err_code |= ERR_WARN;
2617 goto out;
2618 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002619
Willy Tarreau3842f002009-06-14 11:39:52 +02002620 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2621 curproxy->options2 &= ~cfg_opts2[optnum].val;
2622
2623 switch (kwm) {
2624 case KWM_STD:
2625 curproxy->options2 |= cfg_opts2[optnum].val;
2626 break;
2627 case KWM_NO:
2628 curproxy->no_options2 |= cfg_opts2[optnum].val;
2629 break;
2630 case KWM_DEF: /* already cleared */
2631 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002632 }
Willy Tarreau93893792009-07-23 13:19:11 +02002633 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002634 }
2635 }
2636
Willy Tarreau3842f002009-06-14 11:39:52 +02002637 if (kwm != KWM_STD) {
2638 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002639 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002642 }
2643
Emeric Brun3a058f32009-06-30 18:26:00 +02002644 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002646 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002648 if (*(args[2]) != '\0') {
2649 if (!strcmp(args[2], "clf")) {
2650 curproxy->options2 |= PR_O2_CLFLOG;
2651 } else {
2652 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002655 }
2656 }
2657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 else if (!strcmp(args[1], "tcplog"))
2659 /* generate a detailed TCP log */
2660 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 else if (!strcmp(args[1], "tcpka")) {
2662 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002663 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002665
2666 if (curproxy->cap & PR_CAP_FE)
2667 curproxy->options |= PR_O_TCP_CLI_KA;
2668 if (curproxy->cap & PR_CAP_BE)
2669 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 }
2671 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002672 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002673 err_code |= ERR_WARN;
2674
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002676 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002677 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002678 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002679 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002680 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002681 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 if (!*args[2]) { /* no argument */
2683 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2684 curproxy->check_len = strlen(DEF_CHECK_REQ);
2685 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002686 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 curproxy->check_req = (char *)malloc(reqlen);
2688 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002689 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002691 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 if (*args[4])
2693 reqlen += strlen(args[4]);
2694 else
2695 reqlen += strlen("HTTP/1.0");
2696
2697 curproxy->check_req = (char *)malloc(reqlen);
2698 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002699 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002701 }
2702 else if (!strcmp(args[1], "ssl-hello-chk")) {
2703 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002704 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002706
Willy Tarreaua534fea2008-08-03 12:19:50 +02002707 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002708 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002709 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002710 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002711 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002712 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 }
Willy Tarreau23677902007-05-08 23:50:35 +02002714 else if (!strcmp(args[1], "smtpchk")) {
2715 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002716 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002717 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002718 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002719 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002720 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002721 curproxy->options |= PR_O_SMTP_CHK;
2722
2723 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2724 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2725 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2726 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2727 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2728 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2729 curproxy->check_req = (char *)malloc(reqlen);
2730 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2731 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2732 } else {
2733 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2734 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2735 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2736 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2737 }
2738 }
2739 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002740 else if (!strcmp(args[1], "mysql-check")) {
2741 /* use MYSQL request to check servers' health */
2742 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002743 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002744 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002745 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002746 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002747 curproxy->options2 |= PR_O2_MYSQL_CHK;
2748 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002749 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002750 int cur_arg;
2751
2752 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2753 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002754 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002755
2756 curproxy->options |= PR_O_FWDFOR;
2757
2758 free(curproxy->fwdfor_hdr_name);
2759 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2760 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2761
2762 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2763 cur_arg = 2;
2764 while (*(args[cur_arg])) {
2765 if (!strcmp(args[cur_arg], "except")) {
2766 /* suboption except - needs additional argument for it */
2767 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2768 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2769 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002772 }
2773 /* flush useless bits */
2774 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002775 cur_arg += 2;
2776 } else if (!strcmp(args[cur_arg], "header")) {
2777 /* suboption header - needs additional argument for it */
2778 if (*(args[cur_arg+1]) == 0) {
2779 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2780 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002783 }
2784 free(curproxy->fwdfor_hdr_name);
2785 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2786 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2787 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002788 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002789 /* unknown suboption - catchall */
2790 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2791 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002794 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002795 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002796 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002797 else if (!strcmp(args[1], "originalto")) {
2798 int cur_arg;
2799
2800 /* insert x-original-to field, but not for the IP address listed as an except.
2801 * set default options (ie: bitfield, header name, etc)
2802 */
2803
2804 curproxy->options |= PR_O_ORGTO;
2805
2806 free(curproxy->orgto_hdr_name);
2807 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2808 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2809
2810 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2811 cur_arg = 2;
2812 while (*(args[cur_arg])) {
2813 if (!strcmp(args[cur_arg], "except")) {
2814 /* suboption except - needs additional argument for it */
2815 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2816 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2817 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002820 }
2821 /* flush useless bits */
2822 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2823 cur_arg += 2;
2824 } else if (!strcmp(args[cur_arg], "header")) {
2825 /* suboption header - needs additional argument for it */
2826 if (*(args[cur_arg+1]) == 0) {
2827 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2828 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002831 }
2832 free(curproxy->orgto_hdr_name);
2833 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2834 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2835 cur_arg += 2;
2836 } else {
2837 /* unknown suboption - catchall */
2838 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2839 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002842 }
2843 } /* end while loop */
2844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 else {
2846 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 }
Willy Tarreau93893792009-07-23 13:19:11 +02002850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002852 else if (!strcmp(args[0], "default_backend")) {
2853 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002855
2856 if (*(args[1]) == 0) {
2857 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002860 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002861 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002862 curproxy->defbe.name = strdup(args[1]);
2863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002866 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002867
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002868 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 /* enable reconnections to dispatch */
2872 curproxy->options |= PR_O_REDISP;
2873 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002874 else if (!strcmp(args[0], "http-check")) {
2875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002877
2878 if (strcmp(args[1], "disable-on-404") == 0) {
2879 /* enable a graceful server shutdown on an HTTP 404 response */
2880 curproxy->options |= PR_O_DISABLE404;
2881 }
Willy Tarreauef781042010-01-27 11:53:01 +01002882 else if (strcmp(args[1], "send-state") == 0) {
2883 /* enable emission of the apparent state of a server in HTTP checks */
2884 curproxy->options2 |= PR_O2_CHK_SNDST;
2885 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002886 else {
2887 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002890 }
2891 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002892 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002893 if (curproxy == &defproxy) {
2894 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002897 }
2898
Willy Tarreaub80c2302007-11-30 20:51:32 +01002899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002901
2902 if (strcmp(args[1], "fail") == 0) {
2903 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002904 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002905 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2906 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002909 }
2910
Willy Tarreauef6494c2010-01-28 17:12:36 +01002911 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002912 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2913 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002916 }
2917 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2918 }
2919 else {
2920 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002923 }
2924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925#ifdef TPROXY
2926 else if (!strcmp(args[0], "transparent")) {
2927 /* enable transparent proxy connections */
2928 curproxy->options |= PR_O_TRANSP;
2929 }
2930#endif
2931 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002932 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002933 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 if (*(args[1]) == 0) {
2936 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 }
2940 curproxy->maxconn = atol(args[1]);
2941 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002942 else if (!strcmp(args[0], "backlog")) { /* backlog */
2943 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002945
2946 if (*(args[1]) == 0) {
2947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002950 }
2951 curproxy->backlog = atol(args[1]);
2952 }
Willy Tarreau86034312006-12-29 00:10:33 +01002953 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002954 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002956
Willy Tarreau86034312006-12-29 00:10:33 +01002957 if (*(args[1]) == 0) {
2958 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002961 }
2962 curproxy->fullconn = atol(args[1]);
2963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2965 if (*(args[1]) == 0) {
2966 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002970 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2971 if (err) {
2972 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2973 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002976 }
2977 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 }
2979 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01002980 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 if (curproxy == &defproxy) {
2982 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002986 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002988
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 if (strchr(args[1], ':') == NULL) {
2990 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01002994 sk = str2sa(args[1]);
2995 if (!sk) {
2996 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 }
3002 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003003 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003005
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003006 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003007 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3008 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003013 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3015 err_code |= ERR_WARN;
3016
3017 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3018 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3019 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3020 }
3021 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3022 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3023 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3024 }
3025 else {
3026 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
3029 }
3030 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003031 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003033 char *rport, *raddr;
3034 short realport = 0;
3035 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003037 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003042 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044
3045 if (!*args[2]) {
3046 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003051
3052 err = invalid_char(args[1]);
3053 if (err) {
3054 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3055 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003058 }
3059
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003060 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003061 struct sockaddr_in *sk;
3062
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003063 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3065 err_code |= ERR_ALERT | ERR_ABORT;
3066 goto out;
3067 }
3068
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003069 /* the servers are linked backwards first */
3070 newsrv->next = curproxy->srv;
3071 curproxy->srv = newsrv;
3072 newsrv->proxy = curproxy;
3073 newsrv->conf.file = file;
3074 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003076 LIST_INIT(&newsrv->pendconns);
3077 do_check = 0;
3078 newsrv->state = SRV_RUNNING; /* early server setup */
3079 newsrv->last_change = now.tv_sec;
3080 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003082 /* several ways to check the port component :
3083 * - IP => port=+0, relative
3084 * - IP: => port=+0, relative
3085 * - IP:N => port=N, absolute
3086 * - IP:+N => port=+N, relative
3087 * - IP:-N => port=-N, relative
3088 */
3089 raddr = strdup(args[2]);
3090 rport = strchr(raddr, ':');
3091 if (rport) {
3092 *rport++ = 0;
3093 realport = atol(rport);
3094 if (!isdigit((unsigned char)*rport))
3095 newsrv->state |= SRV_MAPPORTS;
3096 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003098
Willy Tarreaud5191e72010-02-09 20:50:45 +01003099 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003100 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003101 if (!sk) {
3102 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106 newsrv->addr = *sk;
3107 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003108
3109 newsrv->check_port = curproxy->defsrv.check_port;
3110 newsrv->inter = curproxy->defsrv.inter;
3111 newsrv->fastinter = curproxy->defsrv.fastinter;
3112 newsrv->downinter = curproxy->defsrv.downinter;
3113 newsrv->rise = curproxy->defsrv.rise;
3114 newsrv->fall = curproxy->defsrv.fall;
3115 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3116 newsrv->minconn = curproxy->defsrv.minconn;
3117 newsrv->maxconn = curproxy->defsrv.maxconn;
3118 newsrv->slowstart = curproxy->defsrv.slowstart;
3119 newsrv->onerror = curproxy->defsrv.onerror;
3120 newsrv->consecutive_errors_limit
3121 = curproxy->defsrv.consecutive_errors_limit;
3122 newsrv->uweight = newsrv->iweight
3123 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003125 newsrv->curfd = -1; /* no health-check in progress */
3126 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003128 cur_arg = 3;
3129 } else {
3130 newsrv = &curproxy->defsrv;
3131 cur_arg = 1;
3132 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003133
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003135 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003136 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003137
3138 if (!*args[cur_arg + 1]) {
3139 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3140 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003143 }
3144
3145 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003146 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003147
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003148 if (newsrv->puid <= 0) {
3149 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003150 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003153 }
3154
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003155 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3156 if (node) {
3157 struct server *target = container_of(node, struct server, conf.id);
3158 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3159 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
3162 }
3163 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003164 cur_arg += 2;
3165 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003166 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 newsrv->cookie = strdup(args[cur_arg + 1]);
3168 newsrv->cklen = strlen(args[cur_arg + 1]);
3169 cur_arg += 2;
3170 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003171 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003172 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3173 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3174 cur_arg += 2;
3175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003177 if (!*args[cur_arg + 1]) {
3178 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3179 file, linenum, args[cur_arg]);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003185 if (newsrv->rise <= 0) {
3186 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3187 file, linenum, args[cur_arg]);
3188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
3190 }
3191
Willy Tarreau96839092010-03-29 10:02:24 +02003192 if (newsrv->health)
3193 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 cur_arg += 2;
3195 }
3196 else if (!strcmp(args[cur_arg], "fall")) {
3197 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003198
3199 if (!*args[cur_arg + 1]) {
3200 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3201 file, linenum, args[cur_arg]);
3202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
3204 }
3205
3206 if (newsrv->fall <= 0) {
3207 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3208 file, linenum, args[cur_arg]);
3209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
3211 }
3212
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 cur_arg += 2;
3214 }
3215 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003216 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3217 if (err) {
3218 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3219 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003222 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003223 if (val <= 0) {
3224 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3225 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003228 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003229 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 cur_arg += 2;
3231 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003232 else if (!strcmp(args[cur_arg], "fastinter")) {
3233 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3234 if (err) {
3235 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3236 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003239 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003240 if (val <= 0) {
3241 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3242 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003245 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003246 newsrv->fastinter = val;
3247 cur_arg += 2;
3248 }
3249 else if (!strcmp(args[cur_arg], "downinter")) {
3250 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3251 if (err) {
3252 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3253 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003256 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003257 if (val <= 0) {
3258 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3259 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003262 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003263 newsrv->downinter = val;
3264 cur_arg += 2;
3265 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003266 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003267 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3268 if (!sk) {
3269 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
3272 }
3273 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003274 cur_arg += 2;
3275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 else if (!strcmp(args[cur_arg], "port")) {
3277 newsrv->check_port = atol(args[cur_arg + 1]);
3278 cur_arg += 2;
3279 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003280 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 newsrv->state |= SRV_BACKUP;
3282 cur_arg ++;
3283 }
3284 else if (!strcmp(args[cur_arg], "weight")) {
3285 int w;
3286 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003287 if (w < 0 || w > 256) {
3288 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003293 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 cur_arg += 2;
3295 }
3296 else if (!strcmp(args[cur_arg], "minconn")) {
3297 newsrv->minconn = atol(args[cur_arg + 1]);
3298 cur_arg += 2;
3299 }
3300 else if (!strcmp(args[cur_arg], "maxconn")) {
3301 newsrv->maxconn = atol(args[cur_arg + 1]);
3302 cur_arg += 2;
3303 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003304 else if (!strcmp(args[cur_arg], "maxqueue")) {
3305 newsrv->maxqueue = atol(args[cur_arg + 1]);
3306 cur_arg += 2;
3307 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003308 else if (!strcmp(args[cur_arg], "slowstart")) {
3309 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003310 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003311 if (err) {
3312 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3313 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003316 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003317 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003318 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3319 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003322 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003323 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003324 cur_arg += 2;
3325 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003326 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003327
3328 if (!*args[cur_arg + 1]) {
3329 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3330 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003333 }
3334
3335 newsrv->trackit = strdup(args[cur_arg + 1]);
3336
3337 cur_arg += 2;
3338 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003339 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 global.maxsock++;
3341 do_check = 1;
3342 cur_arg += 1;
3343 }
Willy Tarreau96839092010-03-29 10:02:24 +02003344 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3345 newsrv->state |= SRV_MAINTAIN;
3346 newsrv->state &= ~SRV_RUNNING;
3347 newsrv->health = 0;
3348 cur_arg += 1;
3349 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003350 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003351 if (!strcmp(args[cur_arg + 1], "none"))
3352 newsrv->observe = HANA_OBS_NONE;
3353 else if (!strcmp(args[cur_arg + 1], "layer4"))
3354 newsrv->observe = HANA_OBS_LAYER4;
3355 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3356 if (curproxy->mode != PR_MODE_HTTP) {
3357 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3358 file, linenum, args[cur_arg + 1]);
3359 err_code |= ERR_ALERT;
3360 }
3361 newsrv->observe = HANA_OBS_LAYER7;
3362 }
3363 else {
3364 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3365 "'l4events', 'http-responses' but get '%s'\n",
3366 file, linenum, args[cur_arg], args[cur_arg + 1]);
3367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
3369 }
3370
3371 cur_arg += 2;
3372 }
3373 else if (!strcmp(args[cur_arg], "on-error")) {
3374 if (!strcmp(args[cur_arg + 1], "fastinter"))
3375 newsrv->onerror = HANA_ONERR_FASTINTER;
3376 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3377 newsrv->onerror = HANA_ONERR_FAILCHK;
3378 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3379 newsrv->onerror = HANA_ONERR_SUDDTH;
3380 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3381 newsrv->onerror = HANA_ONERR_MARKDWN;
3382 else {
3383 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3384 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3385 file, linenum, args[cur_arg], args[cur_arg + 1]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389
3390 cur_arg += 2;
3391 }
3392 else if (!strcmp(args[cur_arg], "error-limit")) {
3393 if (!*args[cur_arg + 1]) {
3394 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3395 file, linenum, args[cur_arg]);
3396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
3398 }
3399
3400 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3401
3402 if (newsrv->consecutive_errors_limit <= 0) {
3403 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3404 file, linenum, args[cur_arg]);
3405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003408 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003409 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003410 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003411 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003412 struct sockaddr_in *sk;
3413
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003415#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003416 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003417 file, linenum, "source", "usesrc");
3418#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003419 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003421#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 }
3425 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003426 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3427 if (!sk) {
3428 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
3431 }
3432 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003433
3434 if (port_low != port_high) {
3435 int i;
3436 if (port_low <= 0 || port_low > 65535 ||
3437 port_high <= 0 || port_high > 65535 ||
3438 port_low > port_high) {
3439 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3440 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003443 }
3444 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3445 for (i = 0; i < newsrv->sport_range->size; i++)
3446 newsrv->sport_range->ports[i] = port_low + i;
3447 }
3448
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003450 while (*(args[cur_arg])) {
3451 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003452#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3453#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003454 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3455 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3456 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003457 err_code |= ERR_ALERT | ERR_FATAL;
3458 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003459 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003460#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003461 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003462 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01003463 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003466 }
3467 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003468 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003469 newsrv->state |= SRV_TPROXY_CLI;
3470 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003471 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003472 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003473 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3474 char *name, *end;
3475
3476 name = args[cur_arg+1] + 7;
3477 while (isspace(*name))
3478 name++;
3479
3480 end = name;
3481 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3482 end++;
3483
3484 newsrv->state &= ~SRV_TPROXY_MASK;
3485 newsrv->state |= SRV_TPROXY_DYN;
3486 newsrv->bind_hdr_name = calloc(1, end - name + 1);
3487 newsrv->bind_hdr_len = end - name;
3488 memcpy(newsrv->bind_hdr_name, name, end - name);
3489 newsrv->bind_hdr_name[end-name] = '\0';
3490 newsrv->bind_hdr_occ = -1;
3491
3492 /* now look for an occurrence number */
3493 while (isspace(*end))
3494 end++;
3495 if (*end == ',') {
3496 end++;
3497 name = end;
3498 if (*end == '-')
3499 end++;
3500 while (isdigit(*end))
3501 end++;
3502 newsrv->bind_hdr_occ = strl2ic(name, end-name);
3503 }
3504
3505 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
3506 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3507 " occurrences values smaller than %d.\n",
3508 file, linenum, MAX_HDR_HISTORY);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01003512 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003513 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3514 if (!sk) {
3515 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003520 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003521 }
3522 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003523#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003524 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003525#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003526 cur_arg += 2;
3527 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003528#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003529 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003530 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003533#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3534 } /* "usesrc" */
3535
3536 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3537#ifdef SO_BINDTODEVICE
3538 if (!*args[cur_arg + 1]) {
3539 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3540 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003543 }
3544 if (newsrv->iface_name)
3545 free(newsrv->iface_name);
3546
3547 newsrv->iface_name = strdup(args[cur_arg + 1]);
3548 newsrv->iface_len = strlen(newsrv->iface_name);
3549 global.last_checks |= LSTCHK_NETADM;
3550#else
3551 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3552 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003555#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003556 cur_arg += 2;
3557 continue;
3558 }
3559 /* this keyword in not an option of "source" */
3560 break;
3561 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003563 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003564 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3565 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003570 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003571 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 +01003572 file, linenum, newsrv->id);
3573 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003574 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 +01003575 file, linenum);
3576
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 }
3580 }
3581
3582 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003583 if (newsrv->trackit) {
3584 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003588 }
3589
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003590 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3591 newsrv->check_port = newsrv->check_addr.sin_port;
3592
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3594 newsrv->check_port = realport; /* by default */
3595 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003596 /* not yet valid, because no port was set on
3597 * the server either. We'll check if we have
3598 * a known port on the first listener.
3599 */
3600 struct listener *l;
3601 l = curproxy->listen;
3602 if (l) {
3603 int port;
3604 port = (l->addr.ss_family == AF_INET6)
3605 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3606 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3607 newsrv->check_port = port;
3608 }
3609 }
3610 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3612 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003615 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003616
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003617 /* Allocate buffer for partial check results... */
3618 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3619 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3620 err_code |= ERR_ALERT | ERR_ABORT;
3621 goto out;
3622 }
3623
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003624 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 newsrv->state |= SRV_CHECKED;
3626 }
3627
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003628 if (!defsrv) {
3629 if (newsrv->state & SRV_BACKUP)
3630 curproxy->srv_bck++;
3631 else
3632 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003633
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003634 newsrv->prev_state = newsrv->state;
3635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 }
3637 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003638 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 int facility;
3640
3641 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3642 curproxy->logfac1 = global.logfac1;
3643 curproxy->logsrv1 = global.logsrv1;
3644 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003645 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 curproxy->logfac2 = global.logfac2;
3647 curproxy->logsrv2 = global.logsrv2;
3648 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003649 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
3651 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003652 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653
3654 facility = get_log_facility(args[2]);
3655 if (facility < 0) {
3656 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3657 exit(1);
3658 }
3659
3660 level = 7; /* max syslog level = debug */
3661 if (*(args[3])) {
3662 level = get_log_level(args[3]);
3663 if (level < 0) {
3664 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3665 exit(1);
3666 }
3667 }
3668
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003669 minlvl = 0; /* limit syslog level to this level (emerg) */
3670 if (*(args[4])) {
3671 minlvl = get_log_level(args[4]);
3672 if (level < 0) {
3673 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3674 exit(1);
3675 }
3676 }
3677
Robert Tsai81ae1952007-12-05 10:47:29 +01003678 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003679 struct sockaddr_un *sk = str2sun(args[1]);
3680 if (!sk) {
3681 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3682 args[1], (int)sizeof(sk->sun_path) - 1);
3683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
3685 }
3686 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003687 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003688 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003689 struct sockaddr_in *sk = str2sa(args[1]);
3690 if (!sk) {
3691 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
3694 }
3695 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003696 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003697 if (!logsrv.u.in.sin_port) {
3698 logsrv.u.in.sin_port =
3699 htons(SYSLOG_PORT);
3700 }
3701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702
3703 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003704 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 curproxy->logfac1 = facility;
3706 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003707 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
3709 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003710 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 curproxy->logfac2 = facility;
3712 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003713 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 }
3715 else {
3716 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
3720 }
3721 else {
3722 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3723 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 }
3727 }
3728 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003729 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003730 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003731
Willy Tarreau977b8e42006-12-29 14:19:17 +01003732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003734
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003736 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3737 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003741
3742 /* we must first clear any optional default setting */
3743 curproxy->options &= ~PR_O_TPXY_MASK;
3744 free(curproxy->iface_name);
3745 curproxy->iface_name = NULL;
3746 curproxy->iface_len = 0;
3747
Willy Tarreaud5191e72010-02-09 20:50:45 +01003748 sk = str2sa(args[1]);
3749 if (!sk) {
3750 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
3753 }
3754 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003756
3757 cur_arg = 2;
3758 while (*(args[cur_arg])) {
3759 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003760#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3761#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003762 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3763 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3764 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003767 }
3768#endif
3769 if (!*args[cur_arg + 1]) {
3770 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3771 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003774 }
3775
3776 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003777 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003778 curproxy->options |= PR_O_TPXY_CLI;
3779 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003780 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003781 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003782 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3783 char *name, *end;
3784
3785 name = args[cur_arg+1] + 7;
3786 while (isspace(*name))
3787 name++;
3788
3789 end = name;
3790 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3791 end++;
3792
3793 curproxy->options &= ~PR_O_TPXY_MASK;
3794 curproxy->options |= PR_O_TPXY_DYN;
3795 curproxy->bind_hdr_name = calloc(1, end - name + 1);
3796 curproxy->bind_hdr_len = end - name;
3797 memcpy(curproxy->bind_hdr_name, name, end - name);
3798 curproxy->bind_hdr_name[end-name] = '\0';
3799 curproxy->bind_hdr_occ = -1;
3800
3801 /* now look for an occurrence number */
3802 while (isspace(*end))
3803 end++;
3804 if (*end == ',') {
3805 end++;
3806 name = end;
3807 if (*end == '-')
3808 end++;
3809 while (isdigit(*end))
3810 end++;
3811 curproxy->bind_hdr_occ = strl2ic(name, end-name);
3812 }
3813
3814 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
3815 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3816 " occurrences values smaller than %d.\n",
3817 file, linenum, MAX_HDR_HISTORY);
3818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
3820 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003821 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003822 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3823 if (!sk) {
3824 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
3827 }
3828 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003829 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003830 }
3831 global.last_checks |= LSTCHK_NETADM;
3832#if !defined(CONFIG_HAP_LINUX_TPROXY)
3833 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003834#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003835#else /* no TPROXY support */
3836 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003837 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003840#endif
3841 cur_arg += 2;
3842 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003843 }
3844
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003845 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3846#ifdef SO_BINDTODEVICE
3847 if (!*args[cur_arg + 1]) {
3848 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3849 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003852 }
3853 if (curproxy->iface_name)
3854 free(curproxy->iface_name);
3855
3856 curproxy->iface_name = strdup(args[cur_arg + 1]);
3857 curproxy->iface_len = strlen(curproxy->iface_name);
3858 global.last_checks |= LSTCHK_NETADM;
3859#else
3860 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3861 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003864#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003865 cur_arg += 2;
3866 continue;
3867 }
3868 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3869 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003874 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3875 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3876 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003881 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3883 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003887
3888 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3889 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003890 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003891 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
3894 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003895 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3896 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003897 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003898 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
3901 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003902 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3903 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003904 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003905 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 }
3908 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3910 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003911 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003912 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 }
3915 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003916 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3917 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003918 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003919 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003922 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003923 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3924 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003925 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003926 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003927 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003928 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003929 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3931 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003932 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003934 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003935 }
3936 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3938 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003939 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003941 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003944 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003950
3951 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3952 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003953 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003954 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 }
3957 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003958 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3959 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003960 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003961 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 }
3964 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3966 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003967 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 }
3971 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003972 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3973 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003974 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003975 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 }
3978 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003979 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3980 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003981 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003982 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003985 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003986 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3987 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003988 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003989 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003990 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003993 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003994
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 if (curproxy == &defproxy) {
3996 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004000 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 if (*(args[1]) == 0) {
4004 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004008
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004009 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4010 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4011 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4012 file, linenum, args[0]);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
4016 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4017 }
4018 else if (*args[2]) {
4019 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4020 file, linenum, args[0], args[2]);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023 }
4024
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004025 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004026 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004027 wl->s = strdup(args[1]);
4028 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004029 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 }
4031 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004032 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004038
Willy Tarreauade5ec42010-01-28 19:33:49 +01004039 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4040 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004041 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004042 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 }
4045 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004046 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4047 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004048 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004049 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 }
4052 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004053 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4054 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004055 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004056 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 }
4059 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004060 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
4066
Willy Tarreauade5ec42010-01-28 19:33:49 +01004067 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4068 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004069 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004070 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 }
4073 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004074 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4075 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004076 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004077 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004079 }
4080 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004081 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4082 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004083 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004084 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 }
4087 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004088 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004089
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090 if (curproxy == &defproxy) {
4091 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004094 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004095 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004096 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004097
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098 if (*(args[1]) == 0) {
4099 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102 }
4103
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004104 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4105 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4106 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4107 file, linenum, args[0]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
4111 err_code |= warnif_cond_requires_req(cond, file, linenum);
4112 }
4113 else if (*args[2]) {
4114 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4115 file, linenum, args[0], args[2]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004120 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004121 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004122 wl->s = strdup(args[1]);
4123 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004124 }
4125 else if (!strcmp(args[0], "errorloc") ||
4126 !strcmp(args[0], "errorloc302") ||
4127 !strcmp(args[0], "errorloc303")) { /* error location */
4128 int errnum, errlen;
4129 char *err;
4130
Willy Tarreau977b8e42006-12-29 14:19:17 +01004131 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004133
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004135 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 }
4139
4140 errnum = atol(args[1]);
4141 if (!strcmp(args[0], "errorloc303")) {
4142 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4143 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4144 } else {
4145 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4146 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4147 }
4148
Willy Tarreau0f772532006-12-23 20:51:41 +01004149 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4150 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004151 chunk_destroy(&curproxy->errmsg[rc]);
4152 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004153 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004156
4157 if (rc >= HTTP_ERR_SIZE) {
4158 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4159 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 free(err);
4161 }
4162 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004163 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4164 int errnum, errlen, fd;
4165 char *err;
4166 struct stat stat;
4167
4168 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004170
4171 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004172 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004175 }
4176
4177 fd = open(args[2], O_RDONLY);
4178 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4179 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4180 file, linenum, args[2], args[1]);
4181 if (fd >= 0)
4182 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004185 }
4186
Willy Tarreau27a674e2009-08-17 07:23:33 +02004187 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004188 errlen = stat.st_size;
4189 } else {
4190 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004191 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004193 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004194 }
4195
4196 err = malloc(errlen); /* malloc() must succeed during parsing */
4197 errnum = read(fd, err, errlen);
4198 if (errnum != errlen) {
4199 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4200 file, linenum, args[2], args[1]);
4201 close(fd);
4202 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004205 }
4206 close(fd);
4207
4208 errnum = atol(args[1]);
4209 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4210 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004211 chunk_destroy(&curproxy->errmsg[rc]);
4212 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004213 break;
4214 }
4215 }
4216
4217 if (rc >= HTTP_ERR_SIZE) {
4218 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4219 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004220 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004221 free(err);
4222 }
4223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004225 struct cfg_kw_list *kwl;
4226 int index;
4227
4228 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4229 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4230 if (kwl->kw[index].section != CFG_LISTEN)
4231 continue;
4232 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4233 /* prepare error message just in case */
4234 snprintf(trash, sizeof(trash),
4235 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004236 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4237 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004238 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004241 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004242 else if (rc > 0) {
4243 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_WARN;
4245 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004246 }
Willy Tarreau93893792009-07-23 13:19:11 +02004247 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004248 }
4249 }
4250 }
4251
Willy Tarreau6daf3432008-01-22 16:44:08 +01004252 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 }
Willy Tarreau93893792009-07-23 13:19:11 +02004256 out:
4257 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258}
4259
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004260int
4261cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4262{
4263
4264 int err_code = 0;
4265 const char *err;
4266
4267 if (!strcmp(args[0], "userlist")) { /* new userlist */
4268 struct userlist *newul;
4269
4270 if (!*args[1]) {
4271 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4272 file, linenum, args[0]);
4273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 }
4276
4277 err = invalid_char(args[1]);
4278 if (err) {
4279 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4280 file, linenum, *err, args[0], args[1]);
4281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
4283 }
4284
4285 for (newul = userlist; newul; newul = newul->next)
4286 if (!strcmp(newul->name, args[1])) {
4287 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4288 file, linenum, args[1]);
4289 err_code |= ERR_WARN;
4290 goto out;
4291 }
4292
4293 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4294 if (!newul) {
4295 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4296 err_code |= ERR_ALERT | ERR_ABORT;
4297 goto out;
4298 }
4299
4300 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4301 newul->name = strdup(args[1]);
4302
4303 if (!newul->groupusers | !newul->name) {
4304 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4305 err_code |= ERR_ALERT | ERR_ABORT;
4306 goto out;
4307 }
4308
4309 newul->next = userlist;
4310 userlist = newul;
4311
4312 } else if (!strcmp(args[0], "group")) { /* new group */
4313 int cur_arg, i;
4314 const char *err;
4315
4316 if (!*args[1]) {
4317 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4318 file, linenum, args[0]);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
4322
4323 err = invalid_char(args[1]);
4324 if (err) {
4325 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4326 file, linenum, *err, args[0], args[1]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330
4331 for(i = 0; i < userlist->grpcnt; i++)
4332 if (!strcmp(userlist->groups[i], args[1])) {
4333 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4334 file, linenum, args[1], userlist->name);
4335 err_code |= ERR_ALERT;
4336 goto out;
4337 }
4338
4339 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4340 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4341 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345
4346 cur_arg = 2;
4347
4348 while (*args[cur_arg]) {
4349 if (!strcmp(args[cur_arg], "users")) {
4350 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4351 cur_arg += 2;
4352 continue;
4353 } else {
4354 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4355 file, linenum, args[0]);
4356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
4358 }
4359 }
4360
4361 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4362 } else if (!strcmp(args[0], "user")) { /* new user */
4363 struct auth_users *newuser;
4364 int cur_arg;
4365
4366 if (!*args[1]) {
4367 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4368 file, linenum, args[0]);
4369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 }
4372
4373 for (newuser = userlist->users; newuser; newuser = newuser->next)
4374 if (!strcmp(newuser->user, args[1])) {
4375 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4376 file, linenum, args[1], userlist->name);
4377 err_code |= ERR_ALERT;
4378 goto out;
4379 }
4380
4381 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4382 if (!newuser) {
4383 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4384 err_code |= ERR_ALERT | ERR_ABORT;
4385 goto out;
4386 }
4387
4388 newuser->user = strdup(args[1]);
4389
4390 newuser->next = userlist->users;
4391 userlist->users = newuser;
4392
4393 cur_arg = 2;
4394
4395 while (*args[cur_arg]) {
4396 if (!strcmp(args[cur_arg], "password")) {
4397#ifndef CONFIG_HAP_CRYPT
4398 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4399 file, linenum);
4400 err_code |= ERR_ALERT;
4401#endif
4402 newuser->pass = strdup(args[cur_arg + 1]);
4403 cur_arg += 2;
4404 continue;
4405 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4406 newuser->pass = strdup(args[cur_arg + 1]);
4407 newuser->flags |= AU_O_INSECURE;
4408 cur_arg += 2;
4409 continue;
4410 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004411 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004412 cur_arg += 2;
4413 continue;
4414 } else {
4415 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4416 file, linenum, args[0]);
4417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
4420 }
4421 } else {
4422 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4423 err_code |= ERR_ALERT | ERR_FATAL;
4424 }
4425
4426out:
4427 return err_code;
4428}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004429
4430/*
4431 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004432 * Returns the error code, 0 if OK, or any combination of :
4433 * - ERR_ABORT: must abort ASAP
4434 * - ERR_FATAL: we can continue parsing but not start the service
4435 * - ERR_WARN: a warning has been emitted
4436 * - ERR_ALERT: an alert has been emitted
4437 * Only the two first ones can stop processing, the two others are just
4438 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004440int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004442 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 FILE *f;
4444 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004446 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 if ((f=fopen(file,"r")) == NULL)
4449 return -1;
4450
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004451 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004452 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004453 char *end;
4454 char *args[MAX_LINE_ARGS + 1];
4455 char *line = thisline;
4456
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 linenum++;
4458
4459 end = line + strlen(line);
4460
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004461 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4462 /* Check if we reached the limit and the last char is not \n.
4463 * Watch out for the last line without the terminating '\n'!
4464 */
4465 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004466 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004468 }
4469
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004471 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 line++;
4473
4474 arg = 0;
4475 args[arg] = line;
4476
4477 while (*line && arg < MAX_LINE_ARGS) {
4478 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4479 * C equivalent value. Other combinations left unchanged (eg: \1).
4480 */
4481 if (*line == '\\') {
4482 int skip = 0;
4483 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4484 *line = line[1];
4485 skip = 1;
4486 }
4487 else if (line[1] == 'r') {
4488 *line = '\r';
4489 skip = 1;
4490 }
4491 else if (line[1] == 'n') {
4492 *line = '\n';
4493 skip = 1;
4494 }
4495 else if (line[1] == 't') {
4496 *line = '\t';
4497 skip = 1;
4498 }
4499 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004500 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 unsigned char hex1, hex2;
4502 hex1 = toupper(line[2]) - '0';
4503 hex2 = toupper(line[3]) - '0';
4504 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4505 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4506 *line = (hex1<<4) + hex2;
4507 skip = 3;
4508 }
4509 else {
4510 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004511 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 }
4513 }
4514 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004515 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 end -= skip;
4517 }
4518 line++;
4519 }
4520 else if (*line == '#' || *line == '\n' || *line == '\r') {
4521 /* end of string, end of loop */
4522 *line = 0;
4523 break;
4524 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004525 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004527 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004528 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 line++;
4530 args[++arg] = line;
4531 }
4532 else {
4533 line++;
4534 }
4535 }
4536
4537 /* empty line */
4538 if (!**args)
4539 continue;
4540
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004541 if (*line) {
4542 /* we had to stop due to too many args.
4543 * Let's terminate the string, print the offending part then cut the
4544 * last arg.
4545 */
4546 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4547 line++;
4548 *line = '\0';
4549
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004550 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004551 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 args[arg] = line;
4554 }
4555
Willy Tarreau540abe42007-05-02 20:50:16 +02004556 /* zero out remaining args and ensure that at least one entry
4557 * is zeroed out.
4558 */
4559 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004560 args[arg] = line;
4561 }
4562
Willy Tarreau3842f002009-06-14 11:39:52 +02004563 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004564 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004565 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004566 for (arg=0; *args[arg+1]; arg++)
4567 args[arg] = args[arg+1]; // shift args after inversion
4568 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004569 else if (!strcmp(args[0], "default")) {
4570 kwm = KWM_DEF;
4571 for (arg=0; *args[arg+1]; arg++)
4572 args[arg] = args[arg+1]; // shift args after inversion
4573 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004574
Willy Tarreau3842f002009-06-14 11:39:52 +02004575 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4576 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004578 }
4579
Willy Tarreau977b8e42006-12-29 14:19:17 +01004580 if (!strcmp(args[0], "listen") ||
4581 !strcmp(args[0], "frontend") ||
4582 !strcmp(args[0], "backend") ||
4583 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004584 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004585 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004586 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004587 cursection = strdup(args[0]);
4588 }
4589 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004591 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004592 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004593 } else if (!strcmp(args[0], "userlist")) {
4594 confsect = CFG_USERLIST;
4595 free(cursection);
4596 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 /* else it's a section keyword */
4599
4600 switch (confsect) {
4601 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 break;
4604 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004605 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004607 case CFG_USERLIST:
4608 err_code |= cfg_parse_users(file, linenum, args, kwm);
4609 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004611 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004614
4615 if (err_code & ERR_ABORT)
4616 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004618 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004619 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004621 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004622}
4623
Willy Tarreaubb925012009-07-23 13:36:36 +02004624/*
4625 * Returns the error code, 0 if OK, or any combination of :
4626 * - ERR_ABORT: must abort ASAP
4627 * - ERR_FATAL: we can continue parsing but not start the service
4628 * - ERR_WARN: a warning has been emitted
4629 * - ERR_ALERT: an alert has been emitted
4630 * Only the two first ones can stop processing, the two others are just
4631 * indicators.
4632 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004633int check_config_validity()
4634{
4635 int cfgerr = 0;
4636 struct proxy *curproxy = NULL;
4637 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004638 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004639 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004640 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641
4642 /*
4643 * Now, check for the integrity of all that we have collected.
4644 */
4645
4646 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004647 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004649 /* first, we will invert the proxy list order */
4650 curproxy = NULL;
4651 while (proxy) {
4652 struct proxy *next;
4653
4654 next = proxy->next;
4655 proxy->next = curproxy;
4656 curproxy = proxy;
4657 if (!next)
4658 break;
4659 proxy = next;
4660 }
4661
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004663 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 }
4667
4668 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004669 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004670 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004671 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004672 unsigned int next_id;
4673
4674 if (!curproxy->uuid) {
4675 /* proxy ID not set, use automatic numbering with first
4676 * spare entry starting with next_pxid.
4677 */
4678 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4679 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4680 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004681 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004682 next_pxid++;
4683
Willy Tarreau55ea7572007-06-17 19:56:27 +02004684
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004686 /* ensure we don't keep listeners uselessly bound */
4687 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 curproxy = curproxy->next;
4689 continue;
4690 }
4691
Willy Tarreauff01a212009-03-15 13:46:16 +01004692 switch (curproxy->mode) {
4693 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004694 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004695 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004696 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4697 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004698 cfgerr++;
4699 }
4700
4701 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004702 Warning("config : servers will be ignored for %s '%s'.\n",
4703 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004704 break;
4705
4706 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004707 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004708 break;
4709
4710 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004711 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004712 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004713 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4714 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004715 cfgerr++;
4716 }
4717 break;
4718 }
4719
4720 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004721 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4722 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 cfgerr++;
4724 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004725
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004726 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004727 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004728 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004729 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4730 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004731 cfgerr++;
4732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004734 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004735 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4736 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004737 cfgerr++;
4738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004740 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004741 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4742 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004743 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004744 }
4745 }
4746 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4747 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4748 /* If no LB algo is set in a backend, and we're not in
4749 * transparent mode, dispatch mode nor proxy mode, we
4750 * want to use balance roundrobin by default.
4751 */
4752 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4753 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
4755 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004756
Willy Tarreau82936582007-11-30 15:20:09 +01004757 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4758 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004759 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4760 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004761 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004762 }
4763
Willy Tarreauef781042010-01-27 11:53:01 +01004764 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4765 curproxy->options &= ~PR_O2_CHK_SNDST;
4766 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4767 "send-state", proxy_type_str(curproxy), curproxy->id);
4768 err_code |= ERR_WARN;
4769 }
4770
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004771 /* if a default backend was specified, let's find it */
4772 if (curproxy->defbe.name) {
4773 struct proxy *target;
4774
Alex Williams96532db2009-11-01 21:27:13 -05004775 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004776 if (!target) {
4777 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4778 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004779 cfgerr++;
4780 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004781 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4782 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004783 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004784 } else {
4785 free(curproxy->defbe.name);
4786 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004787 /* we force the backend to be present on at least all of
4788 * the frontend's processes.
4789 */
4790 target->bind_proc = curproxy->bind_proc ?
4791 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
4793 }
4794
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004795 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004796 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4797 /* map jump target for ACT_SETBE in req_rep chain */
4798 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004799 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004800 struct proxy *target;
4801
Willy Tarreaua496b602006-12-17 23:15:24 +01004802 if (exp->action != ACT_SETBE)
4803 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004804
Alex Williams96532db2009-11-01 21:27:13 -05004805 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004806 if (!target) {
4807 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4808 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004809 cfgerr++;
4810 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004811 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4812 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004813 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004814 } else {
4815 free((void *)exp->replace);
4816 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004817 /* we force the backend to be present on at least all of
4818 * the frontend's processes.
4819 */
4820 target->bind_proc = curproxy->bind_proc ?
4821 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004822 }
4823 }
4824 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004825
4826 /* find the target proxy for 'use_backend' rules */
4827 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004828 struct proxy *target;
4829
Alex Williams96532db2009-11-01 21:27:13 -05004830 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004831
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004832 if (!target) {
4833 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4834 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004835 cfgerr++;
4836 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004837 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4838 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004839 cfgerr++;
4840 } else {
4841 free((void *)rule->be.name);
4842 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004843 /* we force the backend to be present on at least all of
4844 * the frontend's processes.
4845 */
4846 target->bind_proc = curproxy->bind_proc ?
4847 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004848 }
4849 }
4850
Emeric Brunb982a3d2010-01-04 15:45:53 +01004851 /* find the target table for 'stick' rules */
4852 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4853 struct proxy *target;
4854
Emeric Brun1d33b292010-01-04 15:47:17 +01004855 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4856 if (mrule->flags & STK_IS_STORE)
4857 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4858
Emeric Brunb982a3d2010-01-04 15:45:53 +01004859 if (mrule->table.name)
4860 target = findproxy(mrule->table.name, PR_CAP_BE);
4861 else
4862 target = curproxy;
4863
4864 if (!target) {
4865 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4866 curproxy->id, mrule->table.name);
4867 cfgerr++;
4868 }
4869 else if (target->table.size == 0) {
4870 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4871 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4872 cfgerr++;
4873 }
4874 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4875 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4876 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4877 cfgerr++;
4878 }
4879 else {
4880 free((void *)mrule->table.name);
4881 mrule->table.t = &(target->table);
4882 }
4883 }
4884
4885 /* find the target table for 'store response' rules */
4886 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4887 struct proxy *target;
4888
Emeric Brun1d33b292010-01-04 15:47:17 +01004889 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4890
Emeric Brunb982a3d2010-01-04 15:45:53 +01004891 if (mrule->table.name)
4892 target = findproxy(mrule->table.name, PR_CAP_BE);
4893 else
4894 target = curproxy;
4895
4896 if (!target) {
4897 Alert("Proxy '%s': unable to find store table '%s'.\n",
4898 curproxy->id, mrule->table.name);
4899 cfgerr++;
4900 }
4901 else if (target->table.size == 0) {
4902 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4903 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4904 cfgerr++;
4905 }
4906 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4907 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4908 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4909 cfgerr++;
4910 }
4911 else {
4912 free((void *)mrule->table.name);
4913 mrule->table.t = &(target->table);
4914 }
4915 }
4916
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004917 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4918 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004919 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4920 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4921 "proxy", curproxy->id);
4922 cfgerr++;
4923 goto out_uri_auth_compat;
4924 }
4925
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004926 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004927 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004928 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004929 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004930
Willy Tarreau95fa4692010-02-01 13:05:50 +01004931 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4932 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004933
4934 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004935 uri_auth_compat_req[i++] = "realm";
4936 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4937 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004938
Willy Tarreau95fa4692010-02-01 13:05:50 +01004939 uri_auth_compat_req[i++] = "unless";
4940 uri_auth_compat_req[i++] = "{";
4941 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4942 uri_auth_compat_req[i++] = "}";
4943 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004944
Willy Tarreau95fa4692010-02-01 13:05:50 +01004945 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4946 if (!req_acl) {
4947 cfgerr++;
4948 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004949 }
4950
Willy Tarreau95fa4692010-02-01 13:05:50 +01004951 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4952
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004953 if (curproxy->uri_auth->auth_realm) {
4954 free(curproxy->uri_auth->auth_realm);
4955 curproxy->uri_auth->auth_realm = NULL;
4956 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004957
4958 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004959 }
4960out_uri_auth_compat:
4961
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004962 cfgerr += acl_find_targets(curproxy);
4963
Willy Tarreau2738a142006-07-08 17:28:09 +02004964 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004965 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004966 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004967 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004968 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004969 " | While not properly invalid, you will certainly encounter various problems\n"
4970 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004971 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004972 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004973 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004974 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004975
Willy Tarreau1fa31262007-12-03 00:36:16 +01004976 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4977 * We must still support older configurations, so let's find out whether those
4978 * parameters have been set or must be copied from contimeouts.
4979 */
4980 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004981 if (!curproxy->timeout.tarpit ||
4982 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004983 /* tarpit timeout not set. We search in the following order:
4984 * default.tarpit, curr.connect, default.connect.
4985 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004986 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004987 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004988 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004989 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004990 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004991 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004992 }
4993 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004994 (!curproxy->timeout.queue ||
4995 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004996 /* queue timeout not set. We search in the following order:
4997 * default.queue, curr.connect, default.connect.
4998 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004999 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005000 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005001 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005002 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005003 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005004 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005005 }
5006 }
5007
Willy Tarreau07a54902010-03-29 18:33:29 +02005008 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005009 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5010 curproxy->check_req = (char *)malloc(curproxy->check_len);
5011 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005012 }
5013
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005014 /* The small pools required for the capture lists */
5015 if (curproxy->nb_req_cap)
5016 curproxy->req_cap_pool = create_pool("ptrcap",
5017 curproxy->nb_req_cap * sizeof(char *),
5018 MEM_F_SHARED);
5019 if (curproxy->nb_rsp_cap)
5020 curproxy->rsp_cap_pool = create_pool("ptrcap",
5021 curproxy->nb_rsp_cap * sizeof(char *),
5022 MEM_F_SHARED);
5023
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005024 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5025 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5026 MEM_F_SHARED);
5027
Willy Tarreau86034312006-12-29 00:10:33 +01005028 /* for backwards compatibility with "listen" instances, if
5029 * fullconn is not set but maxconn is set, then maxconn
5030 * is used.
5031 */
5032 if (!curproxy->fullconn)
5033 curproxy->fullconn = curproxy->maxconn;
5034
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 /* first, we will invert the servers list order */
5036 newsrv = NULL;
5037 while (curproxy->srv) {
5038 struct server *next;
5039
5040 next = curproxy->srv->next;
5041 curproxy->srv->next = newsrv;
5042 newsrv = curproxy->srv;
5043 if (!next)
5044 break;
5045 curproxy->srv = next;
5046 }
5047
Willy Tarreau20697042007-11-15 23:26:18 +01005048 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005049 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005051 /* We have to initialize the server lookup mechanism depending
5052 * on what LB algorithm was choosen.
5053 */
5054
5055 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5056 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5057 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005058 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5059 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5060 init_server_map(curproxy);
5061 } else {
5062 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5063 fwrr_init_server_groups(curproxy);
5064 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005065 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005066
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005067 case BE_LB_KIND_LC:
5068 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005069 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005070 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005071
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005072 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005073 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5074 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5075 chash_init_server_tree(curproxy);
5076 } else {
5077 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5078 init_server_map(curproxy);
5079 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005080 break;
5081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082
5083 if (curproxy->options & PR_O_LOGASAP)
5084 curproxy->to_log &= ~LW_BYTES;
5085
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005086 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5087 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5088 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5089 proxy_type_str(curproxy), curproxy->id);
5090 err_code |= ERR_WARN;
5091 }
5092
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005093 if (curproxy->mode != PR_MODE_HTTP) {
5094 int optnum;
5095
5096 if (curproxy->options & PR_O_COOK_ANY) {
5097 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5098 proxy_type_str(curproxy), curproxy->id);
5099 err_code |= ERR_WARN;
5100 }
5101
5102 if (curproxy->uri_auth) {
5103 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5104 proxy_type_str(curproxy), curproxy->id);
5105 err_code |= ERR_WARN;
5106 curproxy->uri_auth = NULL;
5107 }
5108
5109 if (curproxy->options & PR_O_FWDFOR) {
5110 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5111 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5112 err_code |= ERR_WARN;
5113 curproxy->options &= ~PR_O_FWDFOR;
5114 }
5115
5116 if (curproxy->options & PR_O_ORGTO) {
5117 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5118 "originalto", proxy_type_str(curproxy), curproxy->id);
5119 err_code |= ERR_WARN;
5120 curproxy->options &= ~PR_O_ORGTO;
5121 }
5122
5123 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5124 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5125 (curproxy->cap & cfg_opts[optnum].cap) &&
5126 (curproxy->options & cfg_opts[optnum].val)) {
5127 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5128 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5129 err_code |= ERR_WARN;
5130 curproxy->options &= ~cfg_opts[optnum].val;
5131 }
5132 }
5133
5134 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5135 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5136 (curproxy->cap & cfg_opts2[optnum].cap) &&
5137 (curproxy->options2 & cfg_opts2[optnum].val)) {
5138 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5139 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5140 err_code |= ERR_WARN;
5141 curproxy->options2 &= ~cfg_opts2[optnum].val;
5142 }
5143 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005144
Willy Tarreauefa5f512010-03-30 20:13:29 +02005145#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005146 if (curproxy->bind_hdr_occ) {
5147 curproxy->bind_hdr_occ = 0;
5148 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5149 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5150 err_code |= ERR_WARN;
5151 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005153 }
5154
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005156 * ensure that we're not cross-dressing a TCP server into HTTP.
5157 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005158 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005159 newsrv = curproxy->srv;
5160 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005161 if (!newsrv->puid) {
5162 /* server ID not set, use automatic numbering with first
5163 * spare entry starting with next_svid.
5164 */
5165 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5166 newsrv->conf.id.key = newsrv->puid = next_id;
5167 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005168 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005169 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005170
Willy Tarreau21d2af32008-02-14 20:25:24 +01005171 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005172 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5173 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005174 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005175 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005176
Willy Tarreauefa5f512010-03-30 20:13:29 +02005177#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005178 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5179 newsrv->bind_hdr_occ = 0;
5180 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5181 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5182 err_code |= ERR_WARN;
5183 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005184#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005185 newsrv = newsrv->next;
5186 }
5187
5188 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005189 * If this server supports a maxconn parameter, it needs a dedicated
5190 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005191 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 */
5193 newsrv = curproxy->srv;
5194 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005195 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 /* Only 'minconn' was specified, or it was higher than or equal
5197 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5198 * this will avoid further useless expensive computations.
5199 */
5200 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005201 } else if (newsrv->maxconn && !newsrv->minconn) {
5202 /* minconn was not specified, so we set it to maxconn */
5203 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005204 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005205 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5206 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005207 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 }
5209
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005210 if (newsrv->trackit) {
5211 struct proxy *px;
5212 struct server *srv;
5213 char *pname, *sname;
5214
5215 pname = newsrv->trackit;
5216 sname = strrchr(pname, '/');
5217
5218 if (sname)
5219 *sname++ = '\0';
5220 else {
5221 sname = pname;
5222 pname = NULL;
5223 }
5224
5225 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005226 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005227 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005228 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5229 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005230 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005231 cfgerr++;
5232 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005233 }
5234 } else
5235 px = curproxy;
5236
5237 srv = findserver(px, sname);
5238 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005239 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5240 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005241 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005242 cfgerr++;
5243 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005244 }
5245
5246 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005247 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005248 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005249 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005250 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005251 cfgerr++;
5252 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005253 }
5254
5255 if (curproxy != px &&
5256 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005257 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005258 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005259 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005260 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005261 cfgerr++;
5262 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005263 }
5264
5265 newsrv->tracked = srv;
5266 newsrv->tracknext = srv->tracknext;
5267 srv->tracknext = newsrv;
5268
5269 free(newsrv->trackit);
5270 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005271 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 newsrv = newsrv->next;
5273 }
5274
Willy Tarreauc1a21672009-08-16 22:37:44 +02005275 if (curproxy->cap & PR_CAP_FE) {
5276 if (curproxy->tcp_req.inspect_delay ||
5277 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5278 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5279
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005280 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005281 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005282 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005283 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005284
5285 /* both TCP and HTTP must check switching rules */
5286 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5287 }
5288
5289 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005290 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005291 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005292 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005293 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005294
Emeric Brunb982a3d2010-01-04 15:45:53 +01005295 /* init table on backend capabilities proxy */
5296 stktable_init(&curproxy->table);
5297
Willy Tarreauc1a21672009-08-16 22:37:44 +02005298 /* If the backend does requires RDP cookie persistence, we have to
5299 * enable the corresponding analyser.
5300 */
5301 if (curproxy->options2 & PR_O2_RDPC_PRST)
5302 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5303 }
5304
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005305 listener = NULL;
5306 while (curproxy->listen) {
5307 struct listener *next;
5308
5309 next = curproxy->listen->next;
5310 curproxy->listen->next = listener;
5311 listener = curproxy->listen;
5312
5313 if (!next)
5314 break;
5315
5316 curproxy->listen = next;
5317 }
5318
Willy Tarreaue6b98942007-10-29 01:09:36 +01005319 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005320 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005321 listener = curproxy->listen;
5322 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005323 if (!listener->luid) {
5324 /* listener ID not set, use automatic numbering with first
5325 * spare entry starting with next_luid.
5326 */
5327 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5328 listener->conf.id.key = listener->luid = next_id;
5329 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005330 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005331 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005332
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005333 /* enable separate counters */
5334 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5335 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5336 if (!listener->name) {
5337 sprintf(trash, "sock-%d", listener->luid);
5338 listener->name = strdup(trash);
5339 }
5340 }
5341
Willy Tarreaue6b98942007-10-29 01:09:36 +01005342 if (curproxy->options & PR_O_TCP_NOLING)
5343 listener->options |= LI_O_NOLINGER;
5344 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005345 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005346 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005347 listener->accept = event_accept;
5348 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005349 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005350 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005351
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005352 /* smart accept mode is automatic in HTTP mode */
5353 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5354 (curproxy->mode == PR_MODE_HTTP &&
5355 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5356 listener->options |= LI_O_NOQUICKACK;
5357
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005358 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005359 listener = listener->next;
5360 }
5361
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 curproxy = curproxy->next;
5363 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005364
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005365 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5366 struct auth_users *curuser;
5367 int g;
5368
5369 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5370 unsigned int group_mask = 0;
5371 char *group = NULL;
5372
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005373 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005374 continue;
5375
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005376 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005377
5378 for (g = 0; g < curuserlist->grpcnt; g++)
5379 if (!strcmp(curuserlist->groups[g], group))
5380 break;
5381
5382 if (g == curuserlist->grpcnt) {
5383 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5384 curuserlist->name, group, curuser->user);
5385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387 }
5388
5389 group_mask |= (1 << g);
5390 }
5391
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005392 free(curuser->u.groups);
5393 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005394 }
5395
5396 for (g = 0; g < curuserlist->grpcnt; g++) {
5397 char *user = NULL;
5398
5399 if (!curuserlist->groupusers[g])
5400 continue;
5401
5402 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5403 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5404 if (!strcmp(curuser->user, user))
5405 break;
5406
5407 if (!curuser) {
5408 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5409 curuserlist->name, user, curuserlist->groups[g]);
5410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
5413
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005414 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005415 }
5416
5417 free(curuserlist->groupusers[g]);
5418 }
5419
5420 free(curuserlist->groupusers);
5421
5422#ifdef DEBUG_AUTH
5423 for (g = 0; g < curuserlist->grpcnt; g++) {
5424 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5425
5426 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5427 if (curuser->group_mask & (1 << g))
5428 fprintf(stderr, " %s", curuser->user);
5429 }
5430
5431 fprintf(stderr, "\n");
5432 }
5433#endif
5434
5435 }
5436
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005437 /*
5438 * Recount currently required checks.
5439 */
5440
5441 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5442 int optnum;
5443
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005444 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5445 if (curproxy->options & cfg_opts[optnum].val)
5446 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005447
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005448 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5449 if (curproxy->options2 & cfg_opts2[optnum].val)
5450 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005451 }
5452
Willy Tarreaubb925012009-07-23 13:36:36 +02005453 if (cfgerr > 0)
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 out:
5456 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457}
5458
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005459/*
5460 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5461 * parsing sessions.
5462 */
5463void cfg_register_keywords(struct cfg_kw_list *kwl)
5464{
5465 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5466}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005468/*
5469 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5470 */
5471void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5472{
5473 LIST_DEL(&kwl->list);
5474 LIST_INIT(&kwl->list);
5475}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476
5477/*
5478 * Local variables:
5479 * c-indent-level: 8
5480 * c-basic-offset: 8
5481 * End:
5482 */