blob: bddb6e73053294fa99ecad22cd834e77d74c5f6b [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 Tarreau66aa61f2009-01-18 21:44:07 +0100153 { NULL, 0, 0, 0 }
154};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155
Willy Tarreau6daf3432008-01-22 16:44:08 +0100156static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200157static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
158int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100159int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200160
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200161/* List head of all known configuration keywords */
162static struct cfg_kw_list cfg_keywords = {
163 .list = LIST_HEAD_INIT(cfg_keywords.list)
164};
165
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166/*
167 * converts <str> to a list of listeners which are dynamically allocated.
168 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
169 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
170 * - <port> is a numerical port from 1 to 65535 ;
171 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
172 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200173 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200175static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176{
177 struct listener *l;
178 char *c, *next, *range, *dupstr;
179 int port, end;
180
181 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200182
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183 while (next && *next) {
184 struct sockaddr_storage ss;
185
186 str = next;
187 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100188 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189 *next++ = 0;
190 }
191
192 /* 2) look for the addr/port delimiter, it's the last colon. */
193 if ((range = strrchr(str, ':')) == NULL) {
194 Alert("Missing port number: '%s'\n", str);
195 goto fail;
196 }
197
198 *range++ = 0;
199
200 if (strrchr(str, ':') != NULL) {
201 /* IPv6 address contains ':' */
202 memset(&ss, 0, sizeof(ss));
203 ss.ss_family = AF_INET6;
204
205 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
206 Alert("Invalid server address: '%s'\n", str);
207 goto fail;
208 }
209 }
210 else {
211 memset(&ss, 0, sizeof(ss));
212 ss.ss_family = AF_INET;
213
214 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
215 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
216 }
217 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
218 struct hostent *he;
219
220 if ((he = gethostbyname(str)) == NULL) {
221 Alert("Invalid server name: '%s'\n", str);
222 goto fail;
223 }
224 else
225 ((struct sockaddr_in *)&ss)->sin_addr =
226 *(struct in_addr *) *(he->h_addr_list);
227 }
228 }
229
230 /* 3) look for the port-end delimiter */
231 if ((c = strchr(range, '-')) != NULL) {
232 *c++ = 0;
233 end = atol(c);
234 }
235 else {
236 end = atol(range);
237 }
238
239 port = atol(range);
240
241 if (port < 1 || port > 65535) {
242 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
243 goto fail;
244 }
245
246 if (end < 1 || end > 65535) {
247 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
248 goto fail;
249 }
250
251 for (; port <= end; port++) {
252 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200253 l->next = curproxy->listen;
254 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
256 l->fd = -1;
257 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100258 l->state = LI_INIT;
259
260 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100262 tcpv6_add_listener(l);
263 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 tcpv4_add_listener(l);
266 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200267
Willy Tarreaue6b98942007-10-29 01:09:36 +0100268 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 } /* end for(port) */
270 } /* end while(next) */
271 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200272 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273 fail:
274 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200275 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276}
277
Willy Tarreau977b8e42006-12-29 14:19:17 +0100278/*
279 * Sends a warning if proxy <proxy> does not have at least one of the
280 * capabilities in <cap>. An optionnal <hint> may be added at the end
281 * of the warning to help the user. Returns 1 if a warning was emitted
282 * or 0 if the condition is valid.
283 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100284int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100285{
286 char *msg;
287
288 switch (cap) {
289 case PR_CAP_BE: msg = "no backend"; break;
290 case PR_CAP_FE: msg = "no frontend"; break;
291 case PR_CAP_RS: msg = "no ruleset"; break;
292 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
293 default: msg = "not enough"; break;
294 }
295
296 if (!(proxy->cap & cap)) {
297 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100298 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299 return 1;
300 }
301 return 0;
302}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303
Willy Tarreau61d18892009-03-31 10:49:21 +0200304/* Report a warning if a rule is placed after a 'block' rule.
305 * Return 1 if the warning has been emitted, otherwise 0.
306 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100307int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200308{
309 if (!LIST_ISEMPTY(&proxy->block_cond)) {
310 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
311 file, line, arg);
312 return 1;
313 }
314 return 0;
315}
316
317/* Report a warning if a rule is placed after a reqrewrite rule.
318 * Return 1 if the warning has been emitted, otherwise 0.
319 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100320int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200321{
322 if (proxy->req_exp) {
323 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
324 file, line, arg);
325 return 1;
326 }
327 return 0;
328}
329
330/* Report a warning if a rule is placed after a reqadd rule.
331 * Return 1 if the warning has been emitted, otherwise 0.
332 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100333int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200334{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100335 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200336 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
337 file, line, arg);
338 return 1;
339 }
340 return 0;
341}
342
343/* Report a warning if a rule is placed after a redirect rule.
344 * Return 1 if the warning has been emitted, otherwise 0.
345 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100346int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200347{
348 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
349 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
350 file, line, arg);
351 return 1;
352 }
353 return 0;
354}
355
356/* Report a warning if a rule is placed after a 'use_backend' rule.
357 * Return 1 if the warning has been emitted, otherwise 0.
358 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100359int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200360{
361 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
362 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
363 file, line, arg);
364 return 1;
365 }
366 return 0;
367}
368
369/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
373 warnif_rule_after_reqadd(proxy, file, line, arg) ||
374 warnif_rule_after_redirect(proxy, file, line, arg) ||
375 warnif_rule_after_use_backend(proxy, file, line, arg);
376}
377
378/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100379int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200380{
381 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
382 warnif_rule_after_redirect(proxy, file, line, arg) ||
383 warnif_rule_after_use_backend(proxy, file, line, arg);
384}
385
386/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100387int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200388{
389 return warnif_rule_after_redirect(proxy, file, line, arg) ||
390 warnif_rule_after_use_backend(proxy, file, line, arg);
391}
392
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100393/* Report it if a request ACL condition uses some response-only parameters. It
394 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
395 * Note that <cond> may be NULL and then will be ignored.
396 */
397static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
398{
399 struct acl *acl;
400
401 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
402 return 0;
403
404 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
405 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
406 file, line, acl ? acl->name : "(unknown)");
407 return ERR_WARN;
408}
409
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100410/* Report it if a request ACL condition uses some request-only volatile parameters.
411 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
412 * Note that <cond> may be NULL and then will be ignored.
413 */
414static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
415{
416 struct acl *acl;
417
418 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
419 return 0;
420
421 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
422 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
423 file, line, acl ? acl->name : "(unknown)");
424 return ERR_WARN;
425}
426
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100427
Willy Tarreaubaaee002006-06-26 02:48:02 +0200428/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200429 * parse a line in a <global> section. Returns the error code, 0 if OK, or
430 * any combination of :
431 * - ERR_ABORT: must abort ASAP
432 * - ERR_FATAL: we can continue parsing but not start the service
433 * - ERR_WARN: a warning has been emitted
434 * - ERR_ALERT: an alert has been emitted
435 * Only the two first ones can stop processing, the two others are just
436 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200437 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200438int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200439{
Willy Tarreau058e9072009-07-20 09:30:05 +0200440 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441
442 if (!strcmp(args[0], "global")) { /* new section */
443 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200445 }
446 else if (!strcmp(args[0], "daemon")) {
447 global.mode |= MODE_DAEMON;
448 }
449 else if (!strcmp(args[0], "debug")) {
450 global.mode |= MODE_DEBUG;
451 }
452 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100453 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200455 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100456 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200457 }
458 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100459 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100462 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100464 else if (!strcmp(args[0], "nosplice")) {
465 global.tune.options &= ~GTUNE_USE_SPLICE;
466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 else if (!strcmp(args[0], "quiet")) {
468 global.mode |= MODE_QUIET;
469 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200470 else if (!strcmp(args[0], "tune.maxpollevents")) {
471 if (global.tune.maxpollevents != 0) {
472 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200473 err_code |= ERR_ALERT;
474 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200475 }
476 if (*(args[1]) == 0) {
477 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200478 err_code |= ERR_ALERT | ERR_FATAL;
479 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200480 }
481 global.tune.maxpollevents = atol(args[1]);
482 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100483 else if (!strcmp(args[0], "tune.maxaccept")) {
484 if (global.tune.maxaccept != 0) {
485 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 err_code |= ERR_ALERT;
487 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100488 }
489 if (*(args[1]) == 0) {
490 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200491 err_code |= ERR_ALERT | ERR_FATAL;
492 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100493 }
494 global.tune.maxaccept = atol(args[1]);
495 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200496 else if (!strcmp(args[0], "tune.bufsize")) {
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.tune.bufsize = atol(args[1]);
503 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
504 global.tune.maxrewrite = global.tune.bufsize / 2;
505 }
506 else if (!strcmp(args[0], "tune.maxrewrite")) {
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 global.tune.maxrewrite = atol(args[1]);
513 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
514 global.tune.maxrewrite = global.tune.bufsize / 2;
515 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100516 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
517 if (global.tune.client_rcvbuf != 0) {
518 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
519 err_code |= ERR_ALERT;
520 goto out;
521 }
522 if (*(args[1]) == 0) {
523 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
524 err_code |= ERR_ALERT | ERR_FATAL;
525 goto out;
526 }
527 global.tune.client_rcvbuf = atol(args[1]);
528 }
529 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
530 if (global.tune.server_rcvbuf != 0) {
531 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
532 err_code |= ERR_ALERT;
533 goto out;
534 }
535 if (*(args[1]) == 0) {
536 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
537 err_code |= ERR_ALERT | ERR_FATAL;
538 goto out;
539 }
540 global.tune.server_rcvbuf = atol(args[1]);
541 }
542 else if (!strcmp(args[0], "tune.sndbuf.client")) {
543 if (global.tune.client_sndbuf != 0) {
544 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
545 err_code |= ERR_ALERT;
546 goto out;
547 }
548 if (*(args[1]) == 0) {
549 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
550 err_code |= ERR_ALERT | ERR_FATAL;
551 goto out;
552 }
553 global.tune.client_sndbuf = atol(args[1]);
554 }
555 else if (!strcmp(args[0], "tune.sndbuf.server")) {
556 if (global.tune.server_sndbuf != 0) {
557 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT;
559 goto out;
560 }
561 if (*(args[1]) == 0) {
562 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
563 err_code |= ERR_ALERT | ERR_FATAL;
564 goto out;
565 }
566 global.tune.server_sndbuf = atol(args[1]);
567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568 else if (!strcmp(args[0], "uid")) {
569 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200570 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200571 err_code |= ERR_ALERT;
572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573 }
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 }
579 global.uid = atol(args[1]);
580 }
581 else if (!strcmp(args[0], "gid")) {
582 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200583 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200584 err_code |= ERR_ALERT;
585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 }
587 if (*(args[1]) == 0) {
588 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200589 err_code |= ERR_ALERT | ERR_FATAL;
590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 }
592 global.gid = atol(args[1]);
593 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200594 /* user/group name handling */
595 else if (!strcmp(args[0], "user")) {
596 struct passwd *ha_user;
597 if (global.uid != 0) {
598 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200599 err_code |= ERR_ALERT;
600 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200601 }
602 errno = 0;
603 ha_user = getpwnam(args[1]);
604 if (ha_user != NULL) {
605 global.uid = (int)ha_user->pw_uid;
606 }
607 else {
608 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 +0200609 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200610 }
611 }
612 else if (!strcmp(args[0], "group")) {
613 struct group *ha_group;
614 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200615 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT;
617 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200618 }
619 errno = 0;
620 ha_group = getgrnam(args[1]);
621 if (ha_group != NULL) {
622 global.gid = (int)ha_group->gr_gid;
623 }
624 else {
625 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 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200627 }
628 }
629 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "nbproc")) {
631 if (global.nbproc != 0) {
632 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200633 err_code |= ERR_ALERT;
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 }
636 if (*(args[1]) == 0) {
637 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT | ERR_FATAL;
639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 }
641 global.nbproc = atol(args[1]);
642 }
643 else if (!strcmp(args[0], "maxconn")) {
644 if (global.maxconn != 0) {
645 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200646 err_code |= ERR_ALERT;
647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 }
649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 }
654 global.maxconn = atol(args[1]);
655#ifdef SYSTEM_MAXCONN
656 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
657 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);
658 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 }
661#endif /* SYSTEM_MAXCONN */
662 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100663 else if (!strcmp(args[0], "maxpipes")) {
664 if (global.maxpipes != 0) {
665 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100668 }
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100673 }
674 global.maxpipes = atol(args[1]);
675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 else if (!strcmp(args[0], "ulimit-n")) {
677 if (global.rlimit_nofile != 0) {
678 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200679 err_code |= ERR_ALERT;
680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681 }
682 if (*(args[1]) == 0) {
683 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200684 err_code |= ERR_ALERT | ERR_FATAL;
685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200686 }
687 global.rlimit_nofile = atol(args[1]);
688 }
689 else if (!strcmp(args[0], "chroot")) {
690 if (global.chroot != NULL) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 }
700 global.chroot = strdup(args[1]);
701 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200702 else if (!strcmp(args[0], "description")) {
703 int i, len=0;
704 char *d;
705
706 if (!*args[1]) {
707 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
708 file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712
713 for(i=1; *args[i]; i++)
714 len += strlen(args[i])+1;
715
716 if (global.desc)
717 free(global.desc);
718
719 global.desc = d = (char *)calloc(1, len);
720
721 d += sprintf(d, "%s", args[1]);
722 for(i=2; *args[i]; i++)
723 d += sprintf(d, " %s", args[i]);
724 }
725 else if (!strcmp(args[0], "node")) {
726 int i;
727 char c;
728
729 for (i=0; args[1][i]; i++) {
730 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100731 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
732 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200733 break;
734 }
735
736 if (!i || args[1][i]) {
737 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
738 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
739 file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743
744 if (global.node)
745 free(global.node);
746
747 global.node = strdup(args[1]);
748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 else if (!strcmp(args[0], "pidfile")) {
750 if (global.pidfile != NULL) {
751 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200752 err_code |= ERR_ALERT;
753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 }
755 if (*(args[1]) == 0) {
756 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 }
760 global.pidfile = strdup(args[1]);
761 }
762 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100763 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200764 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765
766 if (*(args[1]) == 0 || *(args[2]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771
772 facility = get_log_facility(args[2]);
773 if (facility < 0) {
774 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT | ERR_FATAL;
776 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778
779 level = 7; /* max syslog level = debug */
780 if (*(args[3])) {
781 level = get_log_level(args[3]);
782 if (level < 0) {
783 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200784 err_code |= ERR_ALERT | ERR_FATAL;
785 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 }
787 }
788
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200789 minlvl = 0; /* limit syslog level to this level (emerg) */
790 if (*(args[4])) {
791 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200793 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200794 err_code |= ERR_ALERT | ERR_FATAL;
795 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200796 }
797 }
798
Robert Tsai81ae1952007-12-05 10:47:29 +0100799 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100800 struct sockaddr_un *sk = str2sun(args[1]);
801 if (!sk) {
802 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
803 args[1], (int)sizeof(sk->sun_path) - 1);
804 err_code |= ERR_ALERT | ERR_FATAL;
805 goto out;
806 }
807 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100808 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100809 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100810 struct sockaddr_in *sk = str2sa(args[1]);
811 if (!sk) {
812 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100817 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100818 if (!logsrv.u.in.sin_port)
819 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821
822 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100823 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 global.logfac1 = facility;
825 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200826 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100829 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200830 global.logfac2 = facility;
831 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200832 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 }
834 else {
835 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200836 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200838 }
839 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
840 if (global.spread_checks != 0) {
841 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200842 err_code |= ERR_ALERT;
843 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200844 }
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200849 }
850 global.spread_checks = atol(args[1]);
851 if (global.spread_checks < 0 || global.spread_checks > 50) {
852 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200853 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200855 }
856 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200857 struct cfg_kw_list *kwl;
858 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200859 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200860
861 list_for_each_entry(kwl, &cfg_keywords.list, list) {
862 for (index = 0; kwl->kw[index].kw != NULL; index++) {
863 if (kwl->kw[index].section != CFG_GLOBAL)
864 continue;
865 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
866 /* prepare error message just in case */
867 snprintf(trash, sizeof(trash),
868 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200869 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
870 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200871 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200872 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200873 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200874 else if (rc > 0) {
875 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200876 err_code |= ERR_WARN;
877 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200878 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200879 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200880 }
881 }
882 }
883
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200887
Willy Tarreau058e9072009-07-20 09:30:05 +0200888 out:
889 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890}
891
Willy Tarreau97cb7802010-01-03 20:23:58 +0100892/* Perform the most basic initialization of a proxy :
893 * memset(), list_init(*), reset_timeouts(*).
894 */
895static void init_new_proxy(struct proxy *p)
896{
897 memset(p, 0, sizeof(struct proxy));
898 LIST_INIT(&p->pendconns);
899 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100900 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100901 LIST_INIT(&p->block_cond);
902 LIST_INIT(&p->redirect_rules);
903 LIST_INIT(&p->mon_fail_cond);
904 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100905 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100906 LIST_INIT(&p->sticking_rules);
907 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100908 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100909 LIST_INIT(&p->req_add);
910 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100911
912 /* Timeouts are defined as -1 */
913 proxy_reset_timeouts(p);
914}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200916void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100918 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 defproxy.mode = PR_MODE_TCP;
920 defproxy.state = PR_STNEW;
921 defproxy.maxconn = cfg_maxpconn;
922 defproxy.conn_retries = CONN_RETRIES;
923 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100924
925 defproxy.defsrv.inter = DEF_CHKINTR;
926 defproxy.defsrv.fastinter = 0;
927 defproxy.defsrv.downinter = 0;
928 defproxy.defsrv.rise = DEF_RISETIME;
929 defproxy.defsrv.fall = DEF_FALLTIME;
930 defproxy.defsrv.check_port = 0;
931 defproxy.defsrv.maxqueue = 0;
932 defproxy.defsrv.minconn = 0;
933 defproxy.defsrv.maxconn = 0;
934 defproxy.defsrv.slowstart = 0;
935 defproxy.defsrv.onerror = DEF_HANA_ONERR;
936 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
937 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938}
939
Willy Tarreauade5ec42010-01-28 19:33:49 +0100940
941static int create_cond_regex_rule(const char *file, int line,
942 struct proxy *px, int dir, int action, int flags,
943 const char *cmd, const char *reg, const char *repl,
944 const char **cond_start)
945{
946 regex_t *preg = NULL;
947 const char *err;
948 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100949 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100950
951 if (px == &defproxy) {
952 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto err;
955 }
956
957 if (*reg == 0) {
958 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto err;
961 }
962
963 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
964 err_code |= ERR_WARN;
965
Willy Tarreau5321c422010-01-28 20:35:13 +0100966 if (cond_start &&
967 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
968 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
969 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
970 file, line, cmd);
971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto err;
973 }
974 }
975 else if (cond_start && **cond_start) {
976 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
977 file, line, cmd, *cond_start);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto err;
980 }
981
982 if (dir == ACL_DIR_REQ)
983 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100984 else
985 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100986
Willy Tarreauade5ec42010-01-28 19:33:49 +0100987 preg = calloc(1, sizeof(regex_t));
988 if (!preg) {
989 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
990 err_code = ERR_ALERT | ERR_FATAL;
991 goto err;
992 }
993
994 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
995 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
996 err_code = ERR_ALERT | ERR_FATAL;
997 goto err;
998 }
999
1000 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001001 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001002 if (repl && err) {
1003 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1004 file, line, cmd, *err);
1005 err_code |= ERR_ALERT | ERR_FATAL;
1006 goto err;
1007 }
1008
1009 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1010 err_code |= ERR_WARN;
1011
1012 return err_code;
1013 err:
1014 free(preg);
1015 return err_code;
1016}
1017
Willy Tarreaubaaee002006-06-26 02:48:02 +02001018/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001019 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001020 * Returns the error code, 0 if OK, or any combination of :
1021 * - ERR_ABORT: must abort ASAP
1022 * - ERR_FATAL: we can continue parsing but not start the service
1023 * - ERR_WARN: a warning has been emitted
1024 * - ERR_ALERT: an alert has been emitted
1025 * Only the two first ones can stop processing, the two others are just
1026 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001028int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029{
1030 static struct proxy *curproxy = NULL;
1031 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001032 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001033 int rc;
1034 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001035 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001036 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037
Willy Tarreau977b8e42006-12-29 14:19:17 +01001038 if (!strcmp(args[0], "listen"))
1039 rc = PR_CAP_LISTEN;
1040 else if (!strcmp(args[0], "frontend"))
1041 rc = PR_CAP_FE | PR_CAP_RS;
1042 else if (!strcmp(args[0], "backend"))
1043 rc = PR_CAP_BE | PR_CAP_RS;
1044 else if (!strcmp(args[0], "ruleset"))
1045 rc = PR_CAP_RS;
1046 else
1047 rc = PR_CAP_NONE;
1048
1049 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 if (!*args[1]) {
1051 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1052 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1053 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001054 err_code |= ERR_ALERT | ERR_ABORT;
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001057
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001058 err = invalid_char(args[1]);
1059 if (err) {
1060 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1061 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001062 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001063 }
1064
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001065 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1066 /*
1067 * If there are two proxies with the same name only following
1068 * combinations are allowed:
1069 *
1070 * listen backend frontend ruleset
1071 * listen - - - -
1072 * backend - - OK -
1073 * frontend - OK - -
1074 * ruleset - - - -
1075 */
1076
1077 if (!strcmp(curproxy->id, args[1]) &&
1078 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1079 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001080 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1081 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1082 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001083 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001084 }
1085 }
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1088 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001089 err_code |= ERR_ALERT | ERR_ABORT;
1090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001092
Willy Tarreau97cb7802010-01-03 20:23:58 +01001093 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 curproxy->next = proxy;
1095 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001096 curproxy->conf.file = file;
1097 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001098 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001100 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101
1102 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001103 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001104 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001105 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001106 err_code |= ERR_FATAL;
1107 goto out;
1108 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001109 new = curproxy->listen;
1110 while (new != last) {
1111 new->conf.file = file;
1112 new->conf.line = linenum;
1113 new = new->next;
1114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115 global.maxsock++;
1116 }
1117
1118 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001119 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1120
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001123 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001124 curproxy->no_options = defproxy.no_options;
1125 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001126 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001127 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001128 curproxy->except_net = defproxy.except_net;
1129 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001130 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001131 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001133 if (defproxy.fwdfor_hdr_len) {
1134 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1135 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1136 }
1137
Willy Tarreaub86db342009-11-30 11:50:16 +01001138 if (defproxy.orgto_hdr_len) {
1139 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1140 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1141 }
1142
Willy Tarreau977b8e42006-12-29 14:19:17 +01001143 if (curproxy->cap & PR_CAP_FE) {
1144 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001145 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001146 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001147
1148 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001149 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1150 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001151
1152 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154
Willy Tarreau977b8e42006-12-29 14:19:17 +01001155 if (curproxy->cap & PR_CAP_BE) {
1156 curproxy->fullconn = defproxy.fullconn;
1157 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158
Willy Tarreau977b8e42006-12-29 14:19:17 +01001159 if (defproxy.check_req)
1160 curproxy->check_req = strdup(defproxy.check_req);
1161 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162
Willy Tarreau977b8e42006-12-29 14:19:17 +01001163 if (defproxy.cookie_name)
1164 curproxy->cookie_name = strdup(defproxy.cookie_name);
1165 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001166 if (defproxy.cookie_domain)
1167 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001168
Emeric Brun647caf12009-06-30 17:57:00 +02001169 if (defproxy.rdp_cookie_name)
1170 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1171 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1172
Willy Tarreau01732802007-11-01 22:48:15 +01001173 if (defproxy.url_param_name)
1174 curproxy->url_param_name = strdup(defproxy.url_param_name);
1175 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001176
Benoitaffb4812009-03-25 13:02:10 +01001177 if (defproxy.hh_name)
1178 curproxy->hh_name = strdup(defproxy.hh_name);
1179 curproxy->hh_len = defproxy.hh_len;
1180 curproxy->hh_match_domain = defproxy.hh_match_domain;
1181
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001182 if (defproxy.iface_name)
1183 curproxy->iface_name = strdup(defproxy.iface_name);
1184 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001185 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001187 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001188 if (defproxy.capture_name)
1189 curproxy->capture_name = strdup(defproxy.capture_name);
1190 curproxy->capture_namelen = defproxy.capture_namelen;
1191 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193
Willy Tarreau977b8e42006-12-29 14:19:17 +01001194 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001195 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001196 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001197 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001198 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001199 curproxy->uri_auth = defproxy.uri_auth;
1200 curproxy->mon_net = defproxy.mon_net;
1201 curproxy->mon_mask = defproxy.mon_mask;
1202 if (defproxy.monitor_uri)
1203 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1204 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001205 if (defproxy.defbe.name)
1206 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001207 }
1208
1209 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001210 curproxy->timeout.connect = defproxy.timeout.connect;
1211 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001212 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001213 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001214 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001215 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001216 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001217 curproxy->source_addr = defproxy.source_addr;
1218 }
1219
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 curproxy->mode = defproxy.mode;
1221 curproxy->logfac1 = defproxy.logfac1;
1222 curproxy->logsrv1 = defproxy.logsrv1;
1223 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001224 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001225 curproxy->logfac2 = defproxy.logfac2;
1226 curproxy->logsrv2 = defproxy.logsrv2;
1227 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001228 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001230 curproxy->conf.used_listener_id = EB_ROOT;
1231 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001232
Willy Tarreau93893792009-07-23 13:19:11 +02001233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001234 }
1235 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1236 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001237 /* FIXME-20070101: we should do this too at the end of the
1238 * config parsing to free all default values.
1239 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001240 free(defproxy.check_req);
1241 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001242 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001243 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001244 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001245 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001246 free(defproxy.capture_name);
1247 free(defproxy.monitor_uri);
1248 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001249 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001250 free(defproxy.fwdfor_hdr_name);
1251 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001252 free(defproxy.orgto_hdr_name);
1253 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001254
Willy Tarreaua534fea2008-08-03 12:19:50 +02001255 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001256 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001257
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 /* we cannot free uri_auth because it might already be used */
1259 init_default_instance();
1260 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001261 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 }
1264 else if (curproxy == NULL) {
1265 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 }
1269
Willy Tarreau977b8e42006-12-29 14:19:17 +01001270
1271 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001273 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001274 int cur_arg;
1275
Willy Tarreaubaaee002006-06-26 02:48:02 +02001276 if (curproxy == &defproxy) {
1277 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001281 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001282 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283
1284 if (strchr(args[1], ':') == NULL) {
1285 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1286 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001290
1291 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001292 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001296
Willy Tarreau90a570f2009-10-04 20:54:54 +02001297 new_listen = curproxy->listen;
1298 while (new_listen != last_listen) {
1299 new_listen->conf.file = file;
1300 new_listen->conf.line = linenum;
1301 new_listen = new_listen->next;
1302 }
1303
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001304 cur_arg = 2;
1305 while (*(args[cur_arg])) {
1306 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1307#ifdef SO_BINDTODEVICE
1308 struct listener *l;
1309
1310 if (!*args[cur_arg + 1]) {
1311 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1312 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001315 }
1316
1317 for (l = curproxy->listen; l != last_listen; l = l->next)
1318 l->interface = strdup(args[cur_arg + 1]);
1319
1320 global.last_checks |= LSTCHK_NETADM;
1321
1322 cur_arg += 2;
1323 continue;
1324#else
1325 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1326 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001329#endif
1330 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001331 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1332#ifdef TCP_MAXSEG
1333 struct listener *l;
1334 int mss;
1335
1336 if (!*args[cur_arg + 1]) {
1337 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001341 }
1342
1343 mss = str2uic(args[cur_arg + 1]);
1344 if (mss < 1 || mss > 65535) {
1345 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1346 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001349 }
1350
1351 for (l = curproxy->listen; l != last_listen; l = l->next)
1352 l->maxseg = mss;
1353
1354 cur_arg += 2;
1355 continue;
1356#else
1357 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1358 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001361#endif
1362 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001363
1364 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1365#ifdef TCP_DEFER_ACCEPT
1366 struct listener *l;
1367
1368 for (l = curproxy->listen; l != last_listen; l = l->next)
1369 l->options |= LI_O_DEF_ACCEPT;
1370
1371 cur_arg ++;
1372 continue;
1373#else
1374 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1375 file, linenum, args[0], args[cur_arg]);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
1378#endif
1379 }
1380
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001381 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001382#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001383 struct listener *l;
1384
1385 for (l = curproxy->listen; l != last_listen; l = l->next)
1386 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001387
1388 cur_arg ++;
1389 continue;
1390#else
1391 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1392 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001395#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001396 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001397
1398 if (!strcmp(args[cur_arg], "name")) {
1399 struct listener *l;
1400
1401 for (l = curproxy->listen; l != last_listen; l = l->next)
1402 l->name = strdup(args[cur_arg + 1]);
1403
1404 cur_arg += 2;
1405 continue;
1406 }
1407
1408 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001409 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001410 struct listener *l;
1411
1412 if (curproxy->listen->next != last_listen) {
1413 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1414 file, linenum, args[cur_arg]);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto out;
1417 }
1418
1419 if (!*args[cur_arg + 1]) {
1420 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1421 file, linenum, args[cur_arg]);
1422 err_code |= ERR_ALERT | ERR_FATAL;
1423 goto out;
1424 }
1425
1426 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001427 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001428
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001429 if (curproxy->listen->luid <= 0) {
1430 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001431 file, linenum);
1432 err_code |= ERR_ALERT | ERR_FATAL;
1433 goto out;
1434 }
1435
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001436 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1437 if (node) {
1438 l = container_of(node, struct listener, conf.id);
1439 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1440 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1441 err_code |= ERR_ALERT | ERR_FATAL;
1442 goto out;
1443 }
1444 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1445
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001446 cur_arg += 2;
1447 continue;
1448 }
1449
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001450 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 +01001451 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001452 err_code |= ERR_ALERT | ERR_FATAL;
1453 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 }
1458 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1459 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1460 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1461 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
1463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001466 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001467
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 /* flush useless bits */
1469 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001472 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001473 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001474 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001475
Willy Tarreau1c47f852006-07-09 08:22:27 +02001476 if (!*args[1]) {
1477 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1478 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001479 err_code |= ERR_ALERT | ERR_FATAL;
1480 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001481 }
1482
Willy Tarreaua534fea2008-08-03 12:19:50 +02001483 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001484 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001485 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001486 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001487 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1488
Willy Tarreau93893792009-07-23 13:19:11 +02001489 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1492 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1493 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1494 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1495 else {
1496 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001497 err_code |= ERR_ALERT | ERR_FATAL;
1498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499 }
1500 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001501 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001502 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001503
1504 if (curproxy == &defproxy) {
1505 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1506 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
1508 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001509 }
1510
1511 if (!*args[1]) {
1512 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1513 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001514 err_code |= ERR_ALERT | ERR_FATAL;
1515 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001516 }
1517
1518 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001519 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001520
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001521 if (curproxy->uuid <= 0) {
1522 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001524 err_code |= ERR_ALERT | ERR_FATAL;
1525 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001526 }
1527
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001528 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1529 if (node) {
1530 struct proxy *target = container_of(node, struct proxy, conf.id);
1531 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1532 file, linenum, proxy_type_str(curproxy), curproxy->id,
1533 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1534 err_code |= ERR_ALERT | ERR_FATAL;
1535 goto out;
1536 }
1537 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001538 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001539 else if (!strcmp(args[0], "description")) {
1540 int i, len=0;
1541 char *d;
1542
Cyril Bonté99ed3272010-01-24 23:29:44 +01001543 if (curproxy == &defproxy) {
1544 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1545 file, linenum, args[0]);
1546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto out;
1548 }
1549
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001550 if (!*args[1]) {
1551 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1552 file, linenum, args[0]);
1553 return -1;
1554 }
1555
1556 for(i=1; *args[i]; i++)
1557 len += strlen(args[i])+1;
1558
1559 d = (char *)calloc(1, len);
1560 curproxy->desc = d;
1561
1562 d += sprintf(d, "%s", args[1]);
1563 for(i=2; *args[i]; i++)
1564 d += sprintf(d, " %s", args[i]);
1565
1566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1568 curproxy->state = PR_STSTOPPED;
1569 }
1570 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1571 curproxy->state = PR_STNEW;
1572 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001573 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1574 int cur_arg = 1;
1575 unsigned int set = 0;
1576
1577 while (*args[cur_arg]) {
1578 int u;
1579 if (strcmp(args[cur_arg], "all") == 0) {
1580 set = 0;
1581 break;
1582 }
1583 else if (strcmp(args[cur_arg], "odd") == 0) {
1584 set |= 0x55555555;
1585 }
1586 else if (strcmp(args[cur_arg], "even") == 0) {
1587 set |= 0xAAAAAAAA;
1588 }
1589 else {
1590 u = str2uic(args[cur_arg]);
1591 if (u < 1 || u > 32) {
1592 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001596 }
1597 if (u > global.nbproc) {
1598 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1599 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001600 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001601 }
1602 set |= 1 << (u - 1);
1603 }
1604 cur_arg++;
1605 }
1606 curproxy->bind_proc = set;
1607 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001608 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001609 if (curproxy == &defproxy) {
1610 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001611 err_code |= ERR_ALERT | ERR_FATAL;
1612 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001613 }
1614
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001615 err = invalid_char(args[1]);
1616 if (err) {
1617 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1618 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001619 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001620 }
1621
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001622 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1623 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1624 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001627 }
1628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1630 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631
Willy Tarreau977b8e42006-12-29 14:19:17 +01001632 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001634
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 if (*(args[1]) == 0) {
1636 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1637 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001641
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001642 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001643 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 curproxy->cookie_name = strdup(args[1]);
1645 curproxy->cookie_len = strlen(curproxy->cookie_name);
1646
1647 cur_arg = 2;
1648 while (*(args[cur_arg])) {
1649 if (!strcmp(args[cur_arg], "rewrite")) {
1650 curproxy->options |= PR_O_COOK_RW;
1651 }
1652 else if (!strcmp(args[cur_arg], "indirect")) {
1653 curproxy->options |= PR_O_COOK_IND;
1654 }
1655 else if (!strcmp(args[cur_arg], "insert")) {
1656 curproxy->options |= PR_O_COOK_INS;
1657 }
1658 else if (!strcmp(args[cur_arg], "nocache")) {
1659 curproxy->options |= PR_O_COOK_NOC;
1660 }
1661 else if (!strcmp(args[cur_arg], "postonly")) {
1662 curproxy->options |= PR_O_COOK_POST;
1663 }
1664 else if (!strcmp(args[cur_arg], "prefix")) {
1665 curproxy->options |= PR_O_COOK_PFX;
1666 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001667 else if (!strcmp(args[cur_arg], "domain")) {
1668 if (!*args[cur_arg + 1]) {
1669 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1670 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001673 }
1674
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001675 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001676 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001677 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1678 " dots nor does not start with a dot."
1679 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001680 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001681 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001682 }
1683
1684 err = invalid_domainchar(args[cur_arg + 1]);
1685 if (err) {
1686 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1687 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001690 }
1691
Willy Tarreau68a897b2009-12-03 23:28:34 +01001692 if (!curproxy->cookie_domain) {
1693 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1694 } else {
1695 /* one domain was already specified, add another one by
1696 * building the string which will be returned along with
1697 * the cookie.
1698 */
1699 char *new_ptr;
1700 int new_len = strlen(curproxy->cookie_domain) +
1701 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1702 new_ptr = malloc(new_len);
1703 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1704 free(curproxy->cookie_domain);
1705 curproxy->cookie_domain = new_ptr;
1706 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001707 cur_arg++;
1708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001710 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 }
1715 cur_arg++;
1716 }
1717 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1718 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1719 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001720 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 }
1722
1723 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1724 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1725 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 }
1728 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001729 else if (!strcmp(args[0], "persist")) { /* persist */
1730 if (*(args[1]) == 0) {
1731 Alert("parsing [%s:%d] : missing persist method.\n",
1732 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001735 }
1736
1737 if (!strncmp(args[1], "rdp-cookie", 10)) {
1738 curproxy->options2 |= PR_O2_RDPC_PRST;
1739
Emeric Brunb982a3d2010-01-04 15:45:53 +01001740 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001741 const char *beg, *end;
1742
1743 beg = args[1] + 11;
1744 end = strchr(beg, ')');
1745
1746 if (!end || end == beg) {
1747 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1748 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001751 }
1752
1753 free(curproxy->rdp_cookie_name);
1754 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1755 curproxy->rdp_cookie_len = end-beg;
1756 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001757 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001758 free(curproxy->rdp_cookie_name);
1759 curproxy->rdp_cookie_name = strdup("msts");
1760 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1761 }
1762 else { /* syntax */
1763 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1764 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001767 }
1768 }
1769 else {
1770 Alert("parsing [%s:%d] : unknown persist method.\n",
1771 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001774 }
1775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001777 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001779 if (curproxy == &defproxy) {
1780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
Willy Tarreau977b8e42006-12-29 14:19:17 +01001785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001789 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 }
1794 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001795 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 curproxy->appsession_name = strdup(args[1]);
1797 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1798 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001799 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1800 if (err) {
1801 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1802 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001805 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001806 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001807
Willy Tarreau51041c72007-09-09 21:56:53 +02001808 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1809 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001810 err_code |= ERR_ALERT | ERR_ABORT;
1811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001813
1814 cur_arg = 6;
1815 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001816 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1817 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001818 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001819 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001820 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001821 } else if (!strcmp(args[cur_arg], "prefix")) {
1822 curproxy->options2 |= PR_O2_AS_PFX;
1823 } else if (!strcmp(args[cur_arg], "mode")) {
1824 if (!*args[cur_arg + 1]) {
1825 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1826 file, linenum, args[0], args[cur_arg]);
1827 err_code |= ERR_ALERT | ERR_FATAL;
1828 goto out;
1829 }
1830
1831 cur_arg++;
1832 if (!strcmp(args[cur_arg], "query-string")) {
1833 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1834 curproxy->options2 |= PR_O2_AS_M_QS;
1835 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1836 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1837 curproxy->options2 |= PR_O2_AS_M_PP;
1838 } else {
1839 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001844 cur_arg++;
1845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 } /* Url App Session */
1847 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001848 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001849 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001850
Willy Tarreaubaaee002006-06-26 02:48:02 +02001851 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001852 if (curproxy == &defproxy) {
1853 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 if (*(args[4]) == 0) {
1859 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1860 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001864 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 curproxy->capture_name = strdup(args[2]);
1866 curproxy->capture_namelen = strlen(curproxy->capture_name);
1867 curproxy->capture_len = atol(args[4]);
1868 if (curproxy->capture_len >= CAPTURE_LEN) {
1869 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1870 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001871 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 curproxy->capture_len = CAPTURE_LEN - 1;
1873 }
1874 curproxy->to_log |= LW_COOKIE;
1875 }
1876 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1877 struct cap_hdr *hdr;
1878
1879 if (curproxy == &defproxy) {
1880 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 +02001881 err_code |= ERR_ALERT | ERR_FATAL;
1882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 }
1884
1885 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1886 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1887 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 }
1891
1892 hdr = calloc(sizeof(struct cap_hdr), 1);
1893 hdr->next = curproxy->req_cap;
1894 hdr->name = strdup(args[3]);
1895 hdr->namelen = strlen(args[3]);
1896 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001897 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 hdr->index = curproxy->nb_req_cap++;
1899 curproxy->req_cap = hdr;
1900 curproxy->to_log |= LW_REQHDR;
1901 }
1902 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1903 struct cap_hdr *hdr;
1904
1905 if (curproxy == &defproxy) {
1906 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 +02001907 err_code |= ERR_ALERT | ERR_FATAL;
1908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 }
1910
1911 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1912 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1913 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001914 err_code |= ERR_ALERT | ERR_FATAL;
1915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 }
1917 hdr = calloc(sizeof(struct cap_hdr), 1);
1918 hdr->next = curproxy->rsp_cap;
1919 hdr->name = strdup(args[3]);
1920 hdr->namelen = strlen(args[3]);
1921 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001922 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 hdr->index = curproxy->nb_rsp_cap++;
1924 curproxy->rsp_cap = hdr;
1925 curproxy->to_log |= LW_RSPHDR;
1926 }
1927 else {
1928 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1929 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 }
1933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001937
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 if (*(args[1]) == 0) {
1939 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 }
1944 curproxy->conn_retries = atol(args[1]);
1945 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001946 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1947 struct req_acl_rule *req_acl;
1948
1949 if (curproxy == &defproxy) {
1950 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1951 err_code |= ERR_ALERT | ERR_FATAL;
1952 goto out;
1953 }
1954
1955
1956 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1957 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1958 file, linenum, args[0]);
1959 err_code |= ERR_WARN;
1960 }
1961
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001962 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001963
1964 if (!req_acl) {
1965 err_code |= ERR_ALERT | ERR_ABORT;
1966 goto out;
1967 }
1968
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001969 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001970 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1971 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001972 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001973 if (curproxy == &defproxy) {
1974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001977 }
1978
Willy Tarreauef6494c2010-01-28 17:12:36 +01001979 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001980 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1981 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001982 err_code |= ERR_ALERT | ERR_FATAL;
1983 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001984 }
1985
Willy Tarreauef6494c2010-01-28 17:12:36 +01001986 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001987 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1988 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001991 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001992
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001993 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001994 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001995 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001996 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001997 struct redirect_rule *rule;
1998 int cur_arg;
1999 int type = REDIRECT_TYPE_NONE;
2000 int code = 302;
2001 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002002 char *cookie = NULL;
2003 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002004 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002005
Cyril Bonté99ed3272010-01-24 23:29:44 +01002006 if (curproxy == &defproxy) {
2007 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
2010 }
2011
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002012 cur_arg = 1;
2013 while (*(args[cur_arg])) {
2014 if (!strcmp(args[cur_arg], "location")) {
2015 if (!*args[cur_arg + 1]) {
2016 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2017 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002020 }
2021
2022 type = REDIRECT_TYPE_LOCATION;
2023 cur_arg++;
2024 destination = args[cur_arg];
2025 }
2026 else if (!strcmp(args[cur_arg], "prefix")) {
2027 if (!*args[cur_arg + 1]) {
2028 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2029 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002030 err_code |= ERR_ALERT | ERR_FATAL;
2031 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002032 }
2033
2034 type = REDIRECT_TYPE_PREFIX;
2035 cur_arg++;
2036 destination = args[cur_arg];
2037 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002038 else if (!strcmp(args[cur_arg], "set-cookie")) {
2039 if (!*args[cur_arg + 1]) {
2040 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2041 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002042 err_code |= ERR_ALERT | ERR_FATAL;
2043 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002044 }
2045
2046 cur_arg++;
2047 cookie = args[cur_arg];
2048 cookie_set = 1;
2049 }
2050 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2051 if (!*args[cur_arg + 1]) {
2052 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2053 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002054 err_code |= ERR_ALERT | ERR_FATAL;
2055 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002056 }
2057
2058 cur_arg++;
2059 cookie = args[cur_arg];
2060 cookie_set = 0;
2061 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002062 else if (!strcmp(args[cur_arg],"code")) {
2063 if (!*args[cur_arg + 1]) {
2064 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2065 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002066 err_code |= ERR_ALERT | ERR_FATAL;
2067 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002068 }
2069 cur_arg++;
2070 code = atol(args[cur_arg]);
2071 if (code < 301 || code > 303) {
2072 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2073 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002076 }
2077 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002078 else if (!strcmp(args[cur_arg],"drop-query")) {
2079 flags |= REDIRECT_FLAG_DROP_QS;
2080 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002081 else if (!strcmp(args[cur_arg],"append-slash")) {
2082 flags |= REDIRECT_FLAG_APPEND_SLASH;
2083 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002084 else if (strcmp(args[cur_arg], "if") == 0 ||
2085 strcmp(args[cur_arg], "unless") == 0) {
2086 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2087 if (!cond) {
2088 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2089 file, linenum, args[0]);
2090 err_code |= ERR_ALERT | ERR_FATAL;
2091 goto out;
2092 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002093 break;
2094 }
2095 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002096 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 +02002097 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002100 }
2101 cur_arg++;
2102 }
2103
2104 if (type == REDIRECT_TYPE_NONE) {
2105 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_ALERT | ERR_FATAL;
2108 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002109 }
2110
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002111 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2112 rule->cond = cond;
2113 rule->rdr_str = strdup(destination);
2114 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002115 if (cookie) {
2116 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002117 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002118 */
2119 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002120 if (cookie_set) {
2121 rule->cookie_str = malloc(rule->cookie_len + 10);
2122 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2123 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2124 rule->cookie_len += 9;
2125 } else {
2126 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002127 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002128 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2129 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002130 }
2131 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002132 rule->type = type;
2133 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002134 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002135 LIST_INIT(&rule->list);
2136 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002137 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002138 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002139 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002140 struct switching_rule *rule;
2141
Willy Tarreaub099aca2008-10-12 17:26:37 +02002142 if (curproxy == &defproxy) {
2143 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002146 }
2147
Willy Tarreau55ea7572007-06-17 19:56:27 +02002148 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002150
2151 if (*(args[1]) == 0) {
2152 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002153 err_code |= ERR_ALERT | ERR_FATAL;
2154 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002155 }
2156
Willy Tarreauef6494c2010-01-28 17:12:36 +01002157 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002158 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2159 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002162 }
2163
Willy Tarreauef6494c2010-01-28 17:12:36 +01002164 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002165 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002166 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002169 }
2170
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002171 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002172
Willy Tarreau55ea7572007-06-17 19:56:27 +02002173 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2174 rule->cond = cond;
2175 rule->be.name = strdup(args[1]);
2176 LIST_INIT(&rule->list);
2177 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2178 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002179 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002180 struct force_persist_rule *rule;
2181
2182 if (curproxy == &defproxy) {
2183 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
2186 }
2187
2188 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2189 err_code |= ERR_WARN;
2190
Willy Tarreauef6494c2010-01-28 17:12:36 +01002191 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002192 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2193 file, linenum, args[0]);
2194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
2196 }
2197
Willy Tarreauef6494c2010-01-28 17:12:36 +01002198 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002199 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2200 file, linenum);
2201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
2203 }
2204
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002205 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002206
2207 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2208 rule->cond = cond;
2209 LIST_INIT(&rule->list);
2210 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2211 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002212 else if (!strcmp(args[0], "stick-table")) {
2213 int myidx = 1;
2214
2215 curproxy->table.type = (unsigned int)-1;
2216 while (*args[myidx]) {
2217 const char *err;
2218
2219 if (strcmp(args[myidx], "size") == 0) {
2220 myidx++;
2221 if (!*(args[myidx])) {
2222 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2223 file, linenum, args[myidx-1]);
2224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
2226 }
2227 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2228 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2229 file, linenum, *err, args[myidx-1]);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002233 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002234 }
2235 else if (strcmp(args[myidx], "expire") == 0) {
2236 myidx++;
2237 if (!*(args[myidx])) {
2238 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2239 file, linenum, args[myidx-1]);
2240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
2242 }
2243 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2244 if (err) {
2245 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2246 file, linenum, *err, args[myidx-1]);
2247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
2249 }
2250 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002251 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002252 }
2253 else if (strcmp(args[myidx], "nopurge") == 0) {
2254 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002255 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002256 }
2257 else if (strcmp(args[myidx], "type") == 0) {
2258 myidx++;
2259 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2260 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2261 file, linenum, args[myidx]);
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
2264 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002265 /* myidx already points to next arg */
2266 }
2267 else {
2268 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2269 file, linenum, args[myidx]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002272 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002273 }
2274
2275 if (!curproxy->table.size) {
2276 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2277 file, linenum);
2278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
2280 }
2281
2282 if (curproxy->table.type == (unsigned int)-1) {
2283 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2284 file, linenum);
2285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
2287 }
2288 }
2289 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002290 struct sticking_rule *rule;
2291 struct pattern_expr *expr;
2292 int myidx = 0;
2293 const char *name = NULL;
2294 int flags;
2295
2296 if (curproxy == &defproxy) {
2297 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301
2302 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2303 err_code |= ERR_WARN;
2304 goto out;
2305 }
2306
2307 myidx++;
2308 if ((strcmp(args[myidx], "store") == 0) ||
2309 (strcmp(args[myidx], "store-request") == 0)) {
2310 myidx++;
2311 flags = STK_IS_STORE;
2312 }
2313 else if (strcmp(args[myidx], "store-response") == 0) {
2314 myidx++;
2315 flags = STK_IS_STORE | STK_ON_RSP;
2316 }
2317 else if (strcmp(args[myidx], "match") == 0) {
2318 myidx++;
2319 flags = STK_IS_MATCH;
2320 }
2321 else if (strcmp(args[myidx], "on") == 0) {
2322 myidx++;
2323 flags = STK_IS_MATCH | STK_IS_STORE;
2324 }
2325 else {
2326 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
2330
2331 if (*(args[myidx]) == 0) {
2332 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
2335 }
2336
2337 expr = pattern_parse_expr(args, &myidx);
2338 if (!expr) {
2339 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
2343
2344 if (flags & STK_ON_RSP) {
2345 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2346 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2347 file, linenum, args[0], expr->fetch->kw);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351 } else {
2352 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2353 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2354 file, linenum, args[0], expr->fetch->kw);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
2358 }
2359
2360 if (strcmp(args[myidx], "table") == 0) {
2361 myidx++;
2362 name = args[myidx++];
2363 }
2364
Willy Tarreauef6494c2010-01-28 17:12:36 +01002365 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2366 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002367 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2368 file, linenum, args[0]);
2369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
2371 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002372 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002373 else if (*(args[myidx])) {
2374 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2375 file, linenum, args[0], args[myidx]);
2376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
2378 }
2379
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002380 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2381
Emeric Brunb982a3d2010-01-04 15:45:53 +01002382 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2383 rule->cond = cond;
2384 rule->expr = expr;
2385 rule->flags = flags;
2386 rule->table.name = name ? strdup(name) : NULL;
2387 LIST_INIT(&rule->list);
2388 if (flags & STK_ON_RSP)
2389 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2390 else
2391 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002394 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002396
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2398 curproxy->uri_auth = NULL; /* we must detach from the default config */
2399
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002400 if (!*args[1]) {
2401 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 } else if (!strcmp(args[1], "uri")) {
2403 if (*(args[2]) == 0) {
2404 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_ABORT;
2410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412 } else if (!strcmp(args[1], "realm")) {
2413 if (*(args[2]) == 0) {
2414 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2418 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_ABORT;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002422 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002423 unsigned interval;
2424
2425 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2426 if (err) {
2427 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2428 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002431 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2432 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_ABORT;
2434 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002435 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002436 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2437 struct req_acl_rule *req_acl;
2438
2439 if (curproxy == &defproxy) {
2440 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
2443 }
2444
2445 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2446 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2447 err_code |= ERR_ALERT | ERR_ABORT;
2448 goto out;
2449 }
2450
2451 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2452 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2453 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2454 file, linenum, args[0]);
2455 err_code |= ERR_WARN;
2456 }
2457
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002458 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002459
2460 if (!req_acl) {
2461 err_code |= ERR_ALERT | ERR_ABORT;
2462 goto out;
2463 }
2464
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002465 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002466 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2467
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 } else if (!strcmp(args[1], "auth")) {
2469 if (*(args[2]) == 0) {
2470 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2474 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_ABORT;
2476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 }
2478 } else if (!strcmp(args[1], "scope")) {
2479 if (*(args[2]) == 0) {
2480 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2484 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_ABORT;
2486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 }
2488 } else if (!strcmp(args[1], "enable")) {
2489 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2490 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_ABORT;
2492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002494 } else if (!strcmp(args[1], "hide-version")) {
2495 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2496 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_ABORT;
2498 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002499 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002500 } else if (!strcmp(args[1], "show-legends")) {
2501 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2502 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2503 err_code |= ERR_ALERT | ERR_ABORT;
2504 goto out;
2505 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002506 } else if (!strcmp(args[1], "show-node")) {
2507
2508 if (*args[2]) {
2509 int i;
2510 char c;
2511
2512 for (i=0; args[2][i]; i++) {
2513 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002514 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2515 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002516 break;
2517 }
2518
2519 if (!i || args[2][i]) {
2520 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2521 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2522 file, linenum, args[0], args[1]);
2523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
2525 }
2526 }
2527
2528 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2529 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2530 err_code |= ERR_ALERT | ERR_ABORT;
2531 goto out;
2532 }
2533 } else if (!strcmp(args[1], "show-desc")) {
2534 char *desc = NULL;
2535
2536 if (*args[2]) {
2537 int i, len=0;
2538 char *d;
2539
2540 for(i=2; *args[i]; i++)
2541 len += strlen(args[i])+1;
2542
2543 desc = d = (char *)calloc(1, len);
2544
2545 d += sprintf(d, "%s", args[2]);
2546 for(i=3; *args[i]; i++)
2547 d += sprintf(d, " %s", args[i]);
2548 }
2549
2550 if (!*args[2] && !global.desc)
2551 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2552 file, linenum, args[1]);
2553 else {
2554 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2555 free(desc);
2556 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2557 err_code |= ERR_ALERT | ERR_ABORT;
2558 goto out;
2559 }
2560 free(desc);
2561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002563stats_error_parsing:
2564 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2565 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 }
2569 }
2570 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002571 int optnum;
2572
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002573 if (*(args[1]) == '\0') {
2574 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002579
2580 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2581 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002582 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2583 err_code |= ERR_WARN;
2584 goto out;
2585 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002586
Willy Tarreau3842f002009-06-14 11:39:52 +02002587 curproxy->no_options &= ~cfg_opts[optnum].val;
2588 curproxy->options &= ~cfg_opts[optnum].val;
2589
2590 switch (kwm) {
2591 case KWM_STD:
2592 curproxy->options |= cfg_opts[optnum].val;
2593 break;
2594 case KWM_NO:
2595 curproxy->no_options |= cfg_opts[optnum].val;
2596 break;
2597 case KWM_DEF: /* already cleared */
2598 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002599 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002600
Willy Tarreau93893792009-07-23 13:19:11 +02002601 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002602 }
2603 }
2604
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002605 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2606 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002607 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2608 err_code |= ERR_WARN;
2609 goto out;
2610 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002611
Willy Tarreau3842f002009-06-14 11:39:52 +02002612 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2613 curproxy->options2 &= ~cfg_opts2[optnum].val;
2614
2615 switch (kwm) {
2616 case KWM_STD:
2617 curproxy->options2 |= cfg_opts2[optnum].val;
2618 break;
2619 case KWM_NO:
2620 curproxy->no_options2 |= cfg_opts2[optnum].val;
2621 break;
2622 case KWM_DEF: /* already cleared */
2623 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002624 }
Willy Tarreau93893792009-07-23 13:19:11 +02002625 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002626 }
2627 }
2628
Willy Tarreau3842f002009-06-14 11:39:52 +02002629 if (kwm != KWM_STD) {
2630 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002631 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002634 }
2635
Emeric Brun3a058f32009-06-30 18:26:00 +02002636 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002638 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002640 if (*(args[2]) != '\0') {
2641 if (!strcmp(args[2], "clf")) {
2642 curproxy->options2 |= PR_O2_CLFLOG;
2643 } else {
2644 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002647 }
2648 }
2649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 else if (!strcmp(args[1], "tcplog"))
2651 /* generate a detailed TCP log */
2652 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 else if (!strcmp(args[1], "tcpka")) {
2654 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002655 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002657
2658 if (curproxy->cap & PR_CAP_FE)
2659 curproxy->options |= PR_O_TCP_CLI_KA;
2660 if (curproxy->cap & PR_CAP_BE)
2661 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 }
2663 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002665 err_code |= ERR_WARN;
2666
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002668 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002669 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002670 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002671 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002672 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002673 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 if (!*args[2]) { /* no argument */
2675 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2676 curproxy->check_len = strlen(DEF_CHECK_REQ);
2677 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002678 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 curproxy->check_req = (char *)malloc(reqlen);
2680 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002681 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002683 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 if (*args[4])
2685 reqlen += strlen(args[4]);
2686 else
2687 reqlen += strlen("HTTP/1.0");
2688
2689 curproxy->check_req = (char *)malloc(reqlen);
2690 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002691 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002693 }
2694 else if (!strcmp(args[1], "ssl-hello-chk")) {
2695 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002696 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002698
Willy Tarreaua534fea2008-08-03 12:19:50 +02002699 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002700 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002701 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002702 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002703 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002704 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
Willy Tarreau23677902007-05-08 23:50:35 +02002706 else if (!strcmp(args[1], "smtpchk")) {
2707 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002708 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002709 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002710 curproxy->options &= ~PR_O_HTTP_CHK;
2711 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002712 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002713 curproxy->options |= PR_O_SMTP_CHK;
2714
2715 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2716 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2717 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2718 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2719 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2720 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2721 curproxy->check_req = (char *)malloc(reqlen);
2722 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2723 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2724 } else {
2725 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2726 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2727 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2728 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2729 }
2730 }
2731 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002732 else if (!strcmp(args[1], "mysql-check")) {
2733 /* use MYSQL request to check servers' health */
2734 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002735 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002736 curproxy->options &= ~PR_O_HTTP_CHK;
2737 curproxy->options &= ~PR_O_SSL3_CHK;
2738 curproxy->options &= ~PR_O_SMTP_CHK;
2739 curproxy->options2 |= PR_O2_MYSQL_CHK;
2740 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002741 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002742 int cur_arg;
2743
2744 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2745 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002746 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002747
2748 curproxy->options |= PR_O_FWDFOR;
2749
2750 free(curproxy->fwdfor_hdr_name);
2751 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2752 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2753
2754 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2755 cur_arg = 2;
2756 while (*(args[cur_arg])) {
2757 if (!strcmp(args[cur_arg], "except")) {
2758 /* suboption except - needs additional argument for it */
2759 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2760 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2761 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002764 }
2765 /* flush useless bits */
2766 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002767 cur_arg += 2;
2768 } else if (!strcmp(args[cur_arg], "header")) {
2769 /* suboption header - needs additional argument for it */
2770 if (*(args[cur_arg+1]) == 0) {
2771 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2772 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002775 }
2776 free(curproxy->fwdfor_hdr_name);
2777 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2778 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2779 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002780 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002781 /* unknown suboption - catchall */
2782 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2783 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002786 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002787 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002788 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002789 else if (!strcmp(args[1], "originalto")) {
2790 int cur_arg;
2791
2792 /* insert x-original-to field, but not for the IP address listed as an except.
2793 * set default options (ie: bitfield, header name, etc)
2794 */
2795
2796 curproxy->options |= PR_O_ORGTO;
2797
2798 free(curproxy->orgto_hdr_name);
2799 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2800 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2801
2802 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2803 cur_arg = 2;
2804 while (*(args[cur_arg])) {
2805 if (!strcmp(args[cur_arg], "except")) {
2806 /* suboption except - needs additional argument for it */
2807 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2808 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2809 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002812 }
2813 /* flush useless bits */
2814 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2815 cur_arg += 2;
2816 } else if (!strcmp(args[cur_arg], "header")) {
2817 /* suboption header - needs additional argument for it */
2818 if (*(args[cur_arg+1]) == 0) {
2819 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2820 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002823 }
2824 free(curproxy->orgto_hdr_name);
2825 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2826 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2827 cur_arg += 2;
2828 } else {
2829 /* unknown suboption - catchall */
2830 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2831 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002834 }
2835 } /* end while loop */
2836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 else {
2838 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
Willy Tarreau93893792009-07-23 13:19:11 +02002842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002843 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002844 else if (!strcmp(args[0], "default_backend")) {
2845 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002847
2848 if (*(args[1]) == 0) {
2849 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002852 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002853 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002854 curproxy->defbe.name = strdup(args[1]);
2855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002857 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002860 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2861 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 /* enable reconnections to dispatch */
2864 curproxy->options |= PR_O_REDISP;
2865 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002866 else if (!strcmp(args[0], "http-check")) {
2867 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002869
2870 if (strcmp(args[1], "disable-on-404") == 0) {
2871 /* enable a graceful server shutdown on an HTTP 404 response */
2872 curproxy->options |= PR_O_DISABLE404;
2873 }
Willy Tarreauef781042010-01-27 11:53:01 +01002874 else if (strcmp(args[1], "send-state") == 0) {
2875 /* enable emission of the apparent state of a server in HTTP checks */
2876 curproxy->options2 |= PR_O2_CHK_SNDST;
2877 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002878 else {
2879 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002882 }
2883 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002884 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002885 if (curproxy == &defproxy) {
2886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002889 }
2890
Willy Tarreaub80c2302007-11-30 20:51:32 +01002891 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002893
2894 if (strcmp(args[1], "fail") == 0) {
2895 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002896 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002897 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2898 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002901 }
2902
Willy Tarreauef6494c2010-01-28 17:12:36 +01002903 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002904 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2905 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002908 }
2909 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2910 }
2911 else {
2912 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002915 }
2916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917#ifdef TPROXY
2918 else if (!strcmp(args[0], "transparent")) {
2919 /* enable transparent proxy connections */
2920 curproxy->options |= PR_O_TRANSP;
2921 }
2922#endif
2923 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002924 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002925 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 if (*(args[1]) == 0) {
2928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 }
2932 curproxy->maxconn = atol(args[1]);
2933 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002934 else if (!strcmp(args[0], "backlog")) { /* backlog */
2935 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002937
2938 if (*(args[1]) == 0) {
2939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002942 }
2943 curproxy->backlog = atol(args[1]);
2944 }
Willy Tarreau86034312006-12-29 00:10:33 +01002945 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002946 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002948
Willy Tarreau86034312006-12-29 00:10:33 +01002949 if (*(args[1]) == 0) {
2950 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002953 }
2954 curproxy->fullconn = atol(args[1]);
2955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2957 if (*(args[1]) == 0) {
2958 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002962 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2963 if (err) {
2964 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2965 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002968 }
2969 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 }
2971 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01002972 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 if (curproxy == &defproxy) {
2974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002978 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002980
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 if (strchr(args[1], ':') == NULL) {
2982 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\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 Tarreaud5191e72010-02-09 20:50:45 +01002986 sk = str2sa(args[1]);
2987 if (!sk) {
2988 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
2989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
2991 }
2992 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 }
2994 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002995 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002997
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002998 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002999 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3000 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003005 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3006 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3007 err_code |= ERR_WARN;
3008
3009 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3010 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3011 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3012 }
3013 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3014 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3015 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3016 }
3017 else {
3018 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
3022 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003023 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003025 char *rport, *raddr;
3026 short realport = 0;
3027 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003029 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003030 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003034 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036
3037 if (!*args[2]) {
3038 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3039 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003043
3044 err = invalid_char(args[1]);
3045 if (err) {
3046 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3047 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003050 }
3051
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003052 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003053 struct sockaddr_in *sk;
3054
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003055 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3056 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3057 err_code |= ERR_ALERT | ERR_ABORT;
3058 goto out;
3059 }
3060
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003061 /* the servers are linked backwards first */
3062 newsrv->next = curproxy->srv;
3063 curproxy->srv = newsrv;
3064 newsrv->proxy = curproxy;
3065 newsrv->conf.file = file;
3066 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003068 LIST_INIT(&newsrv->pendconns);
3069 do_check = 0;
3070 newsrv->state = SRV_RUNNING; /* early server setup */
3071 newsrv->last_change = now.tv_sec;
3072 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003074 /* several ways to check the port component :
3075 * - IP => port=+0, relative
3076 * - IP: => port=+0, relative
3077 * - IP:N => port=N, absolute
3078 * - IP:+N => port=+N, relative
3079 * - IP:-N => port=-N, relative
3080 */
3081 raddr = strdup(args[2]);
3082 rport = strchr(raddr, ':');
3083 if (rport) {
3084 *rport++ = 0;
3085 realport = atol(rport);
3086 if (!isdigit((unsigned char)*rport))
3087 newsrv->state |= SRV_MAPPORTS;
3088 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003090
Willy Tarreaud5191e72010-02-09 20:50:45 +01003091 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003092 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003093 if (!sk) {
3094 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
3098 newsrv->addr = *sk;
3099 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003100
3101 newsrv->check_port = curproxy->defsrv.check_port;
3102 newsrv->inter = curproxy->defsrv.inter;
3103 newsrv->fastinter = curproxy->defsrv.fastinter;
3104 newsrv->downinter = curproxy->defsrv.downinter;
3105 newsrv->rise = curproxy->defsrv.rise;
3106 newsrv->fall = curproxy->defsrv.fall;
3107 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3108 newsrv->minconn = curproxy->defsrv.minconn;
3109 newsrv->maxconn = curproxy->defsrv.maxconn;
3110 newsrv->slowstart = curproxy->defsrv.slowstart;
3111 newsrv->onerror = curproxy->defsrv.onerror;
3112 newsrv->consecutive_errors_limit
3113 = curproxy->defsrv.consecutive_errors_limit;
3114 newsrv->uweight = newsrv->iweight
3115 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003117 newsrv->curfd = -1; /* no health-check in progress */
3118 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003120 cur_arg = 3;
3121 } else {
3122 newsrv = &curproxy->defsrv;
3123 cur_arg = 1;
3124 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003125
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003127 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003128 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003129
3130 if (!*args[cur_arg + 1]) {
3131 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3132 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003135 }
3136
3137 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003138 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003139
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003140 if (newsrv->puid <= 0) {
3141 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003142 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003145 }
3146
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003147 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3148 if (node) {
3149 struct server *target = container_of(node, struct server, conf.id);
3150 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3151 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
3154 }
3155 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003156 cur_arg += 2;
3157 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003158 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 newsrv->cookie = strdup(args[cur_arg + 1]);
3160 newsrv->cklen = strlen(args[cur_arg + 1]);
3161 cur_arg += 2;
3162 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003163 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003164 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3165 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3166 cur_arg += 2;
3167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003169 if (!*args[cur_arg + 1]) {
3170 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3171 file, linenum, args[cur_arg]);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
3175
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003177 if (newsrv->rise <= 0) {
3178 Alert("parsing [%s:%d]: '%s' has to be > 0.\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->health = newsrv->rise;
3185 cur_arg += 2;
3186 }
3187 else if (!strcmp(args[cur_arg], "fall")) {
3188 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003189
3190 if (!*args[cur_arg + 1]) {
3191 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3192 file, linenum, args[cur_arg]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196
3197 if (newsrv->fall <= 0) {
3198 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3199 file, linenum, args[cur_arg]);
3200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
3202 }
3203
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 cur_arg += 2;
3205 }
3206 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003207 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3208 if (err) {
3209 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3210 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003213 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003214 if (val <= 0) {
3215 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3216 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003219 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003220 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 cur_arg += 2;
3222 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003223 else if (!strcmp(args[cur_arg], "fastinter")) {
3224 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3225 if (err) {
3226 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3227 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003230 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003231 if (val <= 0) {
3232 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3233 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003236 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003237 newsrv->fastinter = val;
3238 cur_arg += 2;
3239 }
3240 else if (!strcmp(args[cur_arg], "downinter")) {
3241 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3242 if (err) {
3243 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3244 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003247 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003248 if (val <= 0) {
3249 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3250 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003253 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003254 newsrv->downinter = val;
3255 cur_arg += 2;
3256 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003257 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003258 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3259 if (!sk) {
3260 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
3263 }
3264 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003265 cur_arg += 2;
3266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 else if (!strcmp(args[cur_arg], "port")) {
3268 newsrv->check_port = atol(args[cur_arg + 1]);
3269 cur_arg += 2;
3270 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003271 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 newsrv->state |= SRV_BACKUP;
3273 cur_arg ++;
3274 }
3275 else if (!strcmp(args[cur_arg], "weight")) {
3276 int w;
3277 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003278 if (w < 0 || w > 256) {
3279 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003284 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 cur_arg += 2;
3286 }
3287 else if (!strcmp(args[cur_arg], "minconn")) {
3288 newsrv->minconn = atol(args[cur_arg + 1]);
3289 cur_arg += 2;
3290 }
3291 else if (!strcmp(args[cur_arg], "maxconn")) {
3292 newsrv->maxconn = atol(args[cur_arg + 1]);
3293 cur_arg += 2;
3294 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003295 else if (!strcmp(args[cur_arg], "maxqueue")) {
3296 newsrv->maxqueue = atol(args[cur_arg + 1]);
3297 cur_arg += 2;
3298 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003299 else if (!strcmp(args[cur_arg], "slowstart")) {
3300 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003301 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003302 if (err) {
3303 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3304 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003307 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003308 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003309 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3310 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003313 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003314 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003315 cur_arg += 2;
3316 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003317 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003318
3319 if (!*args[cur_arg + 1]) {
3320 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3321 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003324 }
3325
3326 newsrv->trackit = strdup(args[cur_arg + 1]);
3327
3328 cur_arg += 2;
3329 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003330 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 global.maxsock++;
3332 do_check = 1;
3333 cur_arg += 1;
3334 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003335 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003336 if (!strcmp(args[cur_arg + 1], "none"))
3337 newsrv->observe = HANA_OBS_NONE;
3338 else if (!strcmp(args[cur_arg + 1], "layer4"))
3339 newsrv->observe = HANA_OBS_LAYER4;
3340 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3341 if (curproxy->mode != PR_MODE_HTTP) {
3342 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3343 file, linenum, args[cur_arg + 1]);
3344 err_code |= ERR_ALERT;
3345 }
3346 newsrv->observe = HANA_OBS_LAYER7;
3347 }
3348 else {
3349 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3350 "'l4events', 'http-responses' but get '%s'\n",
3351 file, linenum, args[cur_arg], args[cur_arg + 1]);
3352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
3354 }
3355
3356 cur_arg += 2;
3357 }
3358 else if (!strcmp(args[cur_arg], "on-error")) {
3359 if (!strcmp(args[cur_arg + 1], "fastinter"))
3360 newsrv->onerror = HANA_ONERR_FASTINTER;
3361 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3362 newsrv->onerror = HANA_ONERR_FAILCHK;
3363 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3364 newsrv->onerror = HANA_ONERR_SUDDTH;
3365 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3366 newsrv->onerror = HANA_ONERR_MARKDWN;
3367 else {
3368 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3369 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3370 file, linenum, args[cur_arg], args[cur_arg + 1]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374
3375 cur_arg += 2;
3376 }
3377 else if (!strcmp(args[cur_arg], "error-limit")) {
3378 if (!*args[cur_arg + 1]) {
3379 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3380 file, linenum, args[cur_arg]);
3381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
3383 }
3384
3385 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3386
3387 if (newsrv->consecutive_errors_limit <= 0) {
3388 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3389 file, linenum, args[cur_arg]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003393 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003394 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003395 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003396 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003397 struct sockaddr_in *sk;
3398
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003400#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003401 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003402 file, linenum, "source", "usesrc");
3403#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003404 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003406#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
3410 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003411 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3412 if (!sk) {
3413 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
3416 }
3417 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003418
3419 if (port_low != port_high) {
3420 int i;
3421 if (port_low <= 0 || port_low > 65535 ||
3422 port_high <= 0 || port_high > 65535 ||
3423 port_low > port_high) {
3424 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3425 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003428 }
3429 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3430 for (i = 0; i < newsrv->sport_range->size; i++)
3431 newsrv->sport_range->ports[i] = port_low + i;
3432 }
3433
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003435 while (*(args[cur_arg])) {
3436 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003437#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3438#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003439 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3440 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3441 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003444 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003445#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003446 if (!*args[cur_arg + 1]) {
3447 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3448 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003451 }
3452 if (!strcmp(args[cur_arg + 1], "client")) {
3453 newsrv->state |= SRV_TPROXY_CLI;
3454 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3455 newsrv->state |= SRV_TPROXY_CIP;
3456 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003457 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3458 if (!sk) {
3459 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003464 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003465 }
3466 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003467#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003468 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003469#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003470 cur_arg += 2;
3471 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003472#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003473 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003474 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003477#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3478 } /* "usesrc" */
3479
3480 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3481#ifdef SO_BINDTODEVICE
3482 if (!*args[cur_arg + 1]) {
3483 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3484 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003487 }
3488 if (newsrv->iface_name)
3489 free(newsrv->iface_name);
3490
3491 newsrv->iface_name = strdup(args[cur_arg + 1]);
3492 newsrv->iface_len = strlen(newsrv->iface_name);
3493 global.last_checks |= LSTCHK_NETADM;
3494#else
3495 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3496 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003499#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003500 cur_arg += 2;
3501 continue;
3502 }
3503 /* this keyword in not an option of "source" */
3504 break;
3505 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003507 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003508 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3509 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003514 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003515 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', '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 +01003516 file, linenum, newsrv->id);
3517 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003518 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 +01003519 file, linenum);
3520
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 }
3524 }
3525
3526 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003527 if (newsrv->trackit) {
3528 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3529 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003532 }
3533
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003534 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3535 newsrv->check_port = newsrv->check_addr.sin_port;
3536
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3538 newsrv->check_port = realport; /* by default */
3539 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003540 /* not yet valid, because no port was set on
3541 * the server either. We'll check if we have
3542 * a known port on the first listener.
3543 */
3544 struct listener *l;
3545 l = curproxy->listen;
3546 if (l) {
3547 int port;
3548 port = (l->addr.ss_family == AF_INET6)
3549 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3550 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3551 newsrv->check_port = port;
3552 }
3553 }
3554 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3556 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003560
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003561 /* Allocate buffer for partial check results... */
3562 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3563 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3564 err_code |= ERR_ALERT | ERR_ABORT;
3565 goto out;
3566 }
3567
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003568 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 newsrv->state |= SRV_CHECKED;
3570 }
3571
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003572 if (!defsrv) {
3573 if (newsrv->state & SRV_BACKUP)
3574 curproxy->srv_bck++;
3575 else
3576 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003577
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003578 newsrv->prev_state = newsrv->state;
3579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
3581 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003582 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 int facility;
3584
3585 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3586 curproxy->logfac1 = global.logfac1;
3587 curproxy->logsrv1 = global.logsrv1;
3588 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003589 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 curproxy->logfac2 = global.logfac2;
3591 curproxy->logsrv2 = global.logsrv2;
3592 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003593 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 }
3595 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003596 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597
3598 facility = get_log_facility(args[2]);
3599 if (facility < 0) {
3600 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3601 exit(1);
3602 }
3603
3604 level = 7; /* max syslog level = debug */
3605 if (*(args[3])) {
3606 level = get_log_level(args[3]);
3607 if (level < 0) {
3608 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3609 exit(1);
3610 }
3611 }
3612
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003613 minlvl = 0; /* limit syslog level to this level (emerg) */
3614 if (*(args[4])) {
3615 minlvl = get_log_level(args[4]);
3616 if (level < 0) {
3617 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3618 exit(1);
3619 }
3620 }
3621
Robert Tsai81ae1952007-12-05 10:47:29 +01003622 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003623 struct sockaddr_un *sk = str2sun(args[1]);
3624 if (!sk) {
3625 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3626 args[1], (int)sizeof(sk->sun_path) - 1);
3627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
3629 }
3630 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003631 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003632 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003633 struct sockaddr_in *sk = str2sa(args[1]);
3634 if (!sk) {
3635 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
3638 }
3639 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003640 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003641 if (!logsrv.u.in.sin_port) {
3642 logsrv.u.in.sin_port =
3643 htons(SYSLOG_PORT);
3644 }
3645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646
3647 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003648 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 curproxy->logfac1 = facility;
3650 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003651 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
3653 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003654 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 curproxy->logfac2 = facility;
3656 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003657 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 }
3659 else {
3660 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 }
3664 }
3665 else {
3666 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3667 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 }
3671 }
3672 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003673 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003674 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003675
Willy Tarreau977b8e42006-12-29 14:19:17 +01003676 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003677 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003678
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003680 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3681 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003685
3686 /* we must first clear any optional default setting */
3687 curproxy->options &= ~PR_O_TPXY_MASK;
3688 free(curproxy->iface_name);
3689 curproxy->iface_name = NULL;
3690 curproxy->iface_len = 0;
3691
Willy Tarreaud5191e72010-02-09 20:50:45 +01003692 sk = str2sa(args[1]);
3693 if (!sk) {
3694 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003700
3701 cur_arg = 2;
3702 while (*(args[cur_arg])) {
3703 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003704#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3705#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003706 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3707 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3708 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003711 }
3712#endif
3713 if (!*args[cur_arg + 1]) {
3714 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3715 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003718 }
3719
3720 if (!strcmp(args[cur_arg + 1], "client")) {
3721 curproxy->options |= PR_O_TPXY_CLI;
3722 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3723 curproxy->options |= PR_O_TPXY_CIP;
3724 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003725 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3726 if (!sk) {
3727 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
3730 }
3731 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003732 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003733 }
3734 global.last_checks |= LSTCHK_NETADM;
3735#if !defined(CONFIG_HAP_LINUX_TPROXY)
3736 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003737#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003738#else /* no TPROXY support */
3739 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003740 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003743#endif
3744 cur_arg += 2;
3745 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003746 }
3747
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003748 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3749#ifdef SO_BINDTODEVICE
3750 if (!*args[cur_arg + 1]) {
3751 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3752 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003755 }
3756 if (curproxy->iface_name)
3757 free(curproxy->iface_name);
3758
3759 curproxy->iface_name = strdup(args[cur_arg + 1]);
3760 curproxy->iface_len = strlen(curproxy->iface_name);
3761 global.last_checks |= LSTCHK_NETADM;
3762#else
3763 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3764 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003767#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003768 cur_arg += 2;
3769 continue;
3770 }
3771 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3772 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003777 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3778 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3779 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003782 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003784 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3786 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003790
3791 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3792 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003793 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003794 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 }
3797 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3799 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003800 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003801 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 }
3804 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3806 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003807 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
3811 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3813 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003814 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3820 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003821 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003822 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003825 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003826 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3827 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003828 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003829 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003830 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003831 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003832 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3834 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003835 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003837 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003838 }
3839 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003840 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3841 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003842 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003843 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003844 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003847 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3849 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003853
3854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3855 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003856 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
3860 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3862 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003863 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
3867 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003868 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3869 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003870 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003871 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
3874 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003875 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3876 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003877 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003878 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
3881 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003882 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3883 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003884 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003885 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003888 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003889 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3890 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003891 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003892 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003893 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003896 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003897
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 if (curproxy == &defproxy) {
3899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003903 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 if (*(args[1]) == 0) {
3907 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003910 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003911
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003912 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3913 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3914 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3915 file, linenum, args[0]);
3916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918 }
3919 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3920 }
3921 else if (*args[2]) {
3922 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3923 file, linenum, args[0], args[2]);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003928 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003929 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003930 wl->s = strdup(args[1]);
3931 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003932 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
3934 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003935 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3937 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003941
Willy Tarreauade5ec42010-01-28 19:33:49 +01003942 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3943 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003944 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003945 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 }
3948 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3950 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003951 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003952 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 }
3955 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003956 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3957 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003958 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
3962 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003963 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3965 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
3969
Willy Tarreauade5ec42010-01-28 19:33:49 +01003970 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3971 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003972 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003973 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 }
3976 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003977 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3978 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003979 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003980 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982 }
3983 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003984 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3985 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003986 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003987 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 }
3990 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003991 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003992
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 if (curproxy == &defproxy) {
3994 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003998 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 if (*(args[1]) == 0) {
4002 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 }
4006
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004007 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4008 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4009 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4010 file, linenum, args[0]);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
4014 err_code |= warnif_cond_requires_req(cond, file, linenum);
4015 }
4016 else if (*args[2]) {
4017 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4018 file, linenum, args[0], args[2]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004023 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004024 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004025 wl->s = strdup(args[1]);
4026 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 }
4028 else if (!strcmp(args[0], "errorloc") ||
4029 !strcmp(args[0], "errorloc302") ||
4030 !strcmp(args[0], "errorloc303")) { /* error location */
4031 int errnum, errlen;
4032 char *err;
4033
Willy Tarreau977b8e42006-12-29 14:19:17 +01004034 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004036
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004038 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
4042
4043 errnum = atol(args[1]);
4044 if (!strcmp(args[0], "errorloc303")) {
4045 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4046 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4047 } else {
4048 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4049 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4050 }
4051
Willy Tarreau0f772532006-12-23 20:51:41 +01004052 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4053 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004054 chunk_destroy(&curproxy->errmsg[rc]);
4055 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004056 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004059
4060 if (rc >= HTTP_ERR_SIZE) {
4061 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4062 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 free(err);
4064 }
4065 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004066 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4067 int errnum, errlen, fd;
4068 char *err;
4069 struct stat stat;
4070
4071 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004073
4074 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004075 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004078 }
4079
4080 fd = open(args[2], O_RDONLY);
4081 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4082 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4083 file, linenum, args[2], args[1]);
4084 if (fd >= 0)
4085 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004088 }
4089
Willy Tarreau27a674e2009-08-17 07:23:33 +02004090 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004091 errlen = stat.st_size;
4092 } else {
4093 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004094 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004095 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004096 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004097 }
4098
4099 err = malloc(errlen); /* malloc() must succeed during parsing */
4100 errnum = read(fd, err, errlen);
4101 if (errnum != errlen) {
4102 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4103 file, linenum, args[2], args[1]);
4104 close(fd);
4105 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004108 }
4109 close(fd);
4110
4111 errnum = atol(args[1]);
4112 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4113 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004114 chunk_destroy(&curproxy->errmsg[rc]);
4115 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004116 break;
4117 }
4118 }
4119
4120 if (rc >= HTTP_ERR_SIZE) {
4121 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4122 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004124 free(err);
4125 }
4126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004128 struct cfg_kw_list *kwl;
4129 int index;
4130
4131 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4132 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4133 if (kwl->kw[index].section != CFG_LISTEN)
4134 continue;
4135 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4136 /* prepare error message just in case */
4137 snprintf(trash, sizeof(trash),
4138 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004139 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4140 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004141 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004144 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004145 else if (rc > 0) {
4146 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004147 err_code |= ERR_WARN;
4148 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004149 }
Willy Tarreau93893792009-07-23 13:19:11 +02004150 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004151 }
4152 }
4153 }
4154
Willy Tarreau6daf3432008-01-22 16:44:08 +01004155 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 }
Willy Tarreau93893792009-07-23 13:19:11 +02004159 out:
4160 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161}
4162
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004163int
4164cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4165{
4166
4167 int err_code = 0;
4168 const char *err;
4169
4170 if (!strcmp(args[0], "userlist")) { /* new userlist */
4171 struct userlist *newul;
4172
4173 if (!*args[1]) {
4174 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4175 file, linenum, args[0]);
4176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
4178 }
4179
4180 err = invalid_char(args[1]);
4181 if (err) {
4182 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4183 file, linenum, *err, args[0], args[1]);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187
4188 for (newul = userlist; newul; newul = newul->next)
4189 if (!strcmp(newul->name, args[1])) {
4190 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4191 file, linenum, args[1]);
4192 err_code |= ERR_WARN;
4193 goto out;
4194 }
4195
4196 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4197 if (!newul) {
4198 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4199 err_code |= ERR_ALERT | ERR_ABORT;
4200 goto out;
4201 }
4202
4203 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4204 newul->name = strdup(args[1]);
4205
4206 if (!newul->groupusers | !newul->name) {
4207 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4208 err_code |= ERR_ALERT | ERR_ABORT;
4209 goto out;
4210 }
4211
4212 newul->next = userlist;
4213 userlist = newul;
4214
4215 } else if (!strcmp(args[0], "group")) { /* new group */
4216 int cur_arg, i;
4217 const char *err;
4218
4219 if (!*args[1]) {
4220 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4221 file, linenum, args[0]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 }
4225
4226 err = invalid_char(args[1]);
4227 if (err) {
4228 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4229 file, linenum, *err, args[0], args[1]);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
4234 for(i = 0; i < userlist->grpcnt; i++)
4235 if (!strcmp(userlist->groups[i], args[1])) {
4236 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4237 file, linenum, args[1], userlist->name);
4238 err_code |= ERR_ALERT;
4239 goto out;
4240 }
4241
4242 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4243 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4244 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
4248
4249 cur_arg = 2;
4250
4251 while (*args[cur_arg]) {
4252 if (!strcmp(args[cur_arg], "users")) {
4253 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4254 cur_arg += 2;
4255 continue;
4256 } else {
4257 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4258 file, linenum, args[0]);
4259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
4262 }
4263
4264 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4265 } else if (!strcmp(args[0], "user")) { /* new user */
4266 struct auth_users *newuser;
4267 int cur_arg;
4268
4269 if (!*args[1]) {
4270 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4271 file, linenum, args[0]);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275
4276 for (newuser = userlist->users; newuser; newuser = newuser->next)
4277 if (!strcmp(newuser->user, args[1])) {
4278 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4279 file, linenum, args[1], userlist->name);
4280 err_code |= ERR_ALERT;
4281 goto out;
4282 }
4283
4284 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4285 if (!newuser) {
4286 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4287 err_code |= ERR_ALERT | ERR_ABORT;
4288 goto out;
4289 }
4290
4291 newuser->user = strdup(args[1]);
4292
4293 newuser->next = userlist->users;
4294 userlist->users = newuser;
4295
4296 cur_arg = 2;
4297
4298 while (*args[cur_arg]) {
4299 if (!strcmp(args[cur_arg], "password")) {
4300#ifndef CONFIG_HAP_CRYPT
4301 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4302 file, linenum);
4303 err_code |= ERR_ALERT;
4304#endif
4305 newuser->pass = strdup(args[cur_arg + 1]);
4306 cur_arg += 2;
4307 continue;
4308 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4309 newuser->pass = strdup(args[cur_arg + 1]);
4310 newuser->flags |= AU_O_INSECURE;
4311 cur_arg += 2;
4312 continue;
4313 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004314 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004315 cur_arg += 2;
4316 continue;
4317 } else {
4318 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4319 file, linenum, args[0]);
4320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
4322 }
4323 }
4324 } else {
4325 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4326 err_code |= ERR_ALERT | ERR_FATAL;
4327 }
4328
4329out:
4330 return err_code;
4331}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332
4333/*
4334 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004335 * Returns the error code, 0 if OK, or any combination of :
4336 * - ERR_ABORT: must abort ASAP
4337 * - ERR_FATAL: we can continue parsing but not start the service
4338 * - ERR_WARN: a warning has been emitted
4339 * - ERR_ALERT: an alert has been emitted
4340 * Only the two first ones can stop processing, the two others are just
4341 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004343int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004345 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 FILE *f;
4347 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004349 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351 if ((f=fopen(file,"r")) == NULL)
4352 return -1;
4353
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004354 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004355 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004356 char *end;
4357 char *args[MAX_LINE_ARGS + 1];
4358 char *line = thisline;
4359
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 linenum++;
4361
4362 end = line + strlen(line);
4363
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004364 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4365 /* Check if we reached the limit and the last char is not \n.
4366 * Watch out for the last line without the terminating '\n'!
4367 */
4368 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004369 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004370 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004371 }
4372
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004374 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375 line++;
4376
4377 arg = 0;
4378 args[arg] = line;
4379
4380 while (*line && arg < MAX_LINE_ARGS) {
4381 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4382 * C equivalent value. Other combinations left unchanged (eg: \1).
4383 */
4384 if (*line == '\\') {
4385 int skip = 0;
4386 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4387 *line = line[1];
4388 skip = 1;
4389 }
4390 else if (line[1] == 'r') {
4391 *line = '\r';
4392 skip = 1;
4393 }
4394 else if (line[1] == 'n') {
4395 *line = '\n';
4396 skip = 1;
4397 }
4398 else if (line[1] == 't') {
4399 *line = '\t';
4400 skip = 1;
4401 }
4402 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004403 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 unsigned char hex1, hex2;
4405 hex1 = toupper(line[2]) - '0';
4406 hex2 = toupper(line[3]) - '0';
4407 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4408 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4409 *line = (hex1<<4) + hex2;
4410 skip = 3;
4411 }
4412 else {
4413 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 }
4416 }
4417 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004418 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 end -= skip;
4420 }
4421 line++;
4422 }
4423 else if (*line == '#' || *line == '\n' || *line == '\r') {
4424 /* end of string, end of loop */
4425 *line = 0;
4426 break;
4427 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004428 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004429 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004430 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004431 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432 line++;
4433 args[++arg] = line;
4434 }
4435 else {
4436 line++;
4437 }
4438 }
4439
4440 /* empty line */
4441 if (!**args)
4442 continue;
4443
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004444 if (*line) {
4445 /* we had to stop due to too many args.
4446 * Let's terminate the string, print the offending part then cut the
4447 * last arg.
4448 */
4449 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4450 line++;
4451 *line = '\0';
4452
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004453 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004454 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 args[arg] = line;
4457 }
4458
Willy Tarreau540abe42007-05-02 20:50:16 +02004459 /* zero out remaining args and ensure that at least one entry
4460 * is zeroed out.
4461 */
4462 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 args[arg] = line;
4464 }
4465
Willy Tarreau3842f002009-06-14 11:39:52 +02004466 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004467 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004468 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004469 for (arg=0; *args[arg+1]; arg++)
4470 args[arg] = args[arg+1]; // shift args after inversion
4471 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004472 else if (!strcmp(args[0], "default")) {
4473 kwm = KWM_DEF;
4474 for (arg=0; *args[arg+1]; arg++)
4475 args[arg] = args[arg+1]; // shift args after inversion
4476 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004477
Willy Tarreau3842f002009-06-14 11:39:52 +02004478 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4479 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004480 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004481 }
4482
Willy Tarreau977b8e42006-12-29 14:19:17 +01004483 if (!strcmp(args[0], "listen") ||
4484 !strcmp(args[0], "frontend") ||
4485 !strcmp(args[0], "backend") ||
4486 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004487 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004489 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004490 cursection = strdup(args[0]);
4491 }
4492 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004494 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004495 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004496 } else if (!strcmp(args[0], "userlist")) {
4497 confsect = CFG_USERLIST;
4498 free(cursection);
4499 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 /* else it's a section keyword */
4502
4503 switch (confsect) {
4504 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 break;
4507 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004508 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004510 case CFG_USERLIST:
4511 err_code |= cfg_parse_users(file, linenum, args, kwm);
4512 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004514 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004515 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004517
4518 if (err_code & ERR_ABORT)
4519 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004521 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004522 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004524 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004525}
4526
Willy Tarreaubb925012009-07-23 13:36:36 +02004527/*
4528 * Returns the error code, 0 if OK, or any combination of :
4529 * - ERR_ABORT: must abort ASAP
4530 * - ERR_FATAL: we can continue parsing but not start the service
4531 * - ERR_WARN: a warning has been emitted
4532 * - ERR_ALERT: an alert has been emitted
4533 * Only the two first ones can stop processing, the two others are just
4534 * indicators.
4535 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004536int check_config_validity()
4537{
4538 int cfgerr = 0;
4539 struct proxy *curproxy = NULL;
4540 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004541 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004542 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004543 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544
4545 /*
4546 * Now, check for the integrity of all that we have collected.
4547 */
4548
4549 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004550 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004552 /* first, we will invert the proxy list order */
4553 curproxy = NULL;
4554 while (proxy) {
4555 struct proxy *next;
4556
4557 next = proxy->next;
4558 proxy->next = curproxy;
4559 curproxy = proxy;
4560 if (!next)
4561 break;
4562 proxy = next;
4563 }
4564
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004566 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 }
4570
4571 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004572 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004573 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004574 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004575 unsigned int next_id;
4576
4577 if (!curproxy->uuid) {
4578 /* proxy ID not set, use automatic numbering with first
4579 * spare entry starting with next_pxid.
4580 */
4581 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4582 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4583 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004584 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004585 next_pxid++;
4586
Willy Tarreau55ea7572007-06-17 19:56:27 +02004587
Willy Tarreaubaaee002006-06-26 02:48:02 +02004588 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004589 /* ensure we don't keep listeners uselessly bound */
4590 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 curproxy = curproxy->next;
4592 continue;
4593 }
4594
Willy Tarreauff01a212009-03-15 13:46:16 +01004595 switch (curproxy->mode) {
4596 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004597 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004598 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004599 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4600 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004601 cfgerr++;
4602 }
4603
4604 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004605 Warning("config : servers will be ignored for %s '%s'.\n",
4606 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004607 break;
4608
4609 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004610 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004611 break;
4612
4613 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004614 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004615 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004616 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4617 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004618 cfgerr++;
4619 }
4620 break;
4621 }
4622
4623 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004624 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4625 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 cfgerr++;
4627 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004628
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004629 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004630 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004631 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004632 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4633 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004634 cfgerr++;
4635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004637 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004638 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4639 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004640 cfgerr++;
4641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004643 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004644 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4645 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004646 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004647 }
4648 }
4649 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4650 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4651 /* If no LB algo is set in a backend, and we're not in
4652 * transparent mode, dispatch mode nor proxy mode, we
4653 * want to use balance roundrobin by default.
4654 */
4655 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4656 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004657 }
4658 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004659
Willy Tarreau82936582007-11-30 15:20:09 +01004660 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4661 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004662 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4663 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004664 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004665 }
4666
Willy Tarreauef781042010-01-27 11:53:01 +01004667 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4668 curproxy->options &= ~PR_O2_CHK_SNDST;
4669 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4670 "send-state", proxy_type_str(curproxy), curproxy->id);
4671 err_code |= ERR_WARN;
4672 }
4673
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004674 /* if a default backend was specified, let's find it */
4675 if (curproxy->defbe.name) {
4676 struct proxy *target;
4677
Alex Williams96532db2009-11-01 21:27:13 -05004678 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004679 if (!target) {
4680 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4681 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004682 cfgerr++;
4683 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004684 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4685 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004686 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004687 } else {
4688 free(curproxy->defbe.name);
4689 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004690 /* we force the backend to be present on at least all of
4691 * the frontend's processes.
4692 */
4693 target->bind_proc = curproxy->bind_proc ?
4694 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 }
4696 }
4697
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004698 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004699 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4700 /* map jump target for ACT_SETBE in req_rep chain */
4701 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004702 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004703 struct proxy *target;
4704
Willy Tarreaua496b602006-12-17 23:15:24 +01004705 if (exp->action != ACT_SETBE)
4706 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004707
Alex Williams96532db2009-11-01 21:27:13 -05004708 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004709 if (!target) {
4710 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4711 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004712 cfgerr++;
4713 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004714 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4715 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004716 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004717 } else {
4718 free((void *)exp->replace);
4719 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004720 /* we force the backend to be present on at least all of
4721 * the frontend's processes.
4722 */
4723 target->bind_proc = curproxy->bind_proc ?
4724 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004725 }
4726 }
4727 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004728
4729 /* find the target proxy for 'use_backend' rules */
4730 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004731 struct proxy *target;
4732
Alex Williams96532db2009-11-01 21:27:13 -05004733 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004734
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004735 if (!target) {
4736 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4737 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004738 cfgerr++;
4739 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004740 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4741 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004742 cfgerr++;
4743 } else {
4744 free((void *)rule->be.name);
4745 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004746 /* we force the backend to be present on at least all of
4747 * the frontend's processes.
4748 */
4749 target->bind_proc = curproxy->bind_proc ?
4750 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004751 }
4752 }
4753
Emeric Brunb982a3d2010-01-04 15:45:53 +01004754 /* find the target table for 'stick' rules */
4755 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4756 struct proxy *target;
4757
Emeric Brun1d33b292010-01-04 15:47:17 +01004758 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4759 if (mrule->flags & STK_IS_STORE)
4760 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4761
Emeric Brunb982a3d2010-01-04 15:45:53 +01004762 if (mrule->table.name)
4763 target = findproxy(mrule->table.name, PR_CAP_BE);
4764 else
4765 target = curproxy;
4766
4767 if (!target) {
4768 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4769 curproxy->id, mrule->table.name);
4770 cfgerr++;
4771 }
4772 else if (target->table.size == 0) {
4773 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4774 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4775 cfgerr++;
4776 }
4777 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4778 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4779 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4780 cfgerr++;
4781 }
4782 else {
4783 free((void *)mrule->table.name);
4784 mrule->table.t = &(target->table);
4785 }
4786 }
4787
4788 /* find the target table for 'store response' rules */
4789 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4790 struct proxy *target;
4791
Emeric Brun1d33b292010-01-04 15:47:17 +01004792 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4793
Emeric Brunb982a3d2010-01-04 15:45:53 +01004794 if (mrule->table.name)
4795 target = findproxy(mrule->table.name, PR_CAP_BE);
4796 else
4797 target = curproxy;
4798
4799 if (!target) {
4800 Alert("Proxy '%s': unable to find store table '%s'.\n",
4801 curproxy->id, mrule->table.name);
4802 cfgerr++;
4803 }
4804 else if (target->table.size == 0) {
4805 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4806 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4807 cfgerr++;
4808 }
4809 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4810 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4811 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4812 cfgerr++;
4813 }
4814 else {
4815 free((void *)mrule->table.name);
4816 mrule->table.t = &(target->table);
4817 }
4818 }
4819
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004820 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4821 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004822 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4823 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4824 "proxy", curproxy->id);
4825 cfgerr++;
4826 goto out_uri_auth_compat;
4827 }
4828
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004829 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004830 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004831 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004832 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004833
Willy Tarreau95fa4692010-02-01 13:05:50 +01004834 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4835 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004836
4837 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004838 uri_auth_compat_req[i++] = "realm";
4839 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4840 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004841
Willy Tarreau95fa4692010-02-01 13:05:50 +01004842 uri_auth_compat_req[i++] = "unless";
4843 uri_auth_compat_req[i++] = "{";
4844 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4845 uri_auth_compat_req[i++] = "}";
4846 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004847
Willy Tarreau95fa4692010-02-01 13:05:50 +01004848 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4849 if (!req_acl) {
4850 cfgerr++;
4851 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004852 }
4853
Willy Tarreau95fa4692010-02-01 13:05:50 +01004854 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4855
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004856 if (curproxy->uri_auth->auth_realm) {
4857 free(curproxy->uri_auth->auth_realm);
4858 curproxy->uri_auth->auth_realm = NULL;
4859 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004860
4861 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004862 }
4863out_uri_auth_compat:
4864
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004865 cfgerr += acl_find_targets(curproxy);
4866
Willy Tarreau2738a142006-07-08 17:28:09 +02004867 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004868 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004869 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004870 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004871 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004872 " | While not properly invalid, you will certainly encounter various problems\n"
4873 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004874 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004875 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004876 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004877 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004878
Willy Tarreau1fa31262007-12-03 00:36:16 +01004879 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4880 * We must still support older configurations, so let's find out whether those
4881 * parameters have been set or must be copied from contimeouts.
4882 */
4883 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004884 if (!curproxy->timeout.tarpit ||
4885 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004886 /* tarpit timeout not set. We search in the following order:
4887 * default.tarpit, curr.connect, default.connect.
4888 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004889 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004890 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004891 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004892 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004893 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004894 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004895 }
4896 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004897 (!curproxy->timeout.queue ||
4898 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004899 /* queue timeout not set. We search in the following order:
4900 * default.queue, curr.connect, default.connect.
4901 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004902 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004903 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004904 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004905 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004906 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004907 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004908 }
4909 }
4910
Willy Tarreauf3c69202006-07-09 16:42:34 +02004911 if (curproxy->options & PR_O_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01004912 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
4913 curproxy->check_req = (char *)malloc(curproxy->check_len);
4914 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02004915 }
4916
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004917 /* The small pools required for the capture lists */
4918 if (curproxy->nb_req_cap)
4919 curproxy->req_cap_pool = create_pool("ptrcap",
4920 curproxy->nb_req_cap * sizeof(char *),
4921 MEM_F_SHARED);
4922 if (curproxy->nb_rsp_cap)
4923 curproxy->rsp_cap_pool = create_pool("ptrcap",
4924 curproxy->nb_rsp_cap * sizeof(char *),
4925 MEM_F_SHARED);
4926
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004927 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4928 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4929 MEM_F_SHARED);
4930
Willy Tarreau86034312006-12-29 00:10:33 +01004931 /* for backwards compatibility with "listen" instances, if
4932 * fullconn is not set but maxconn is set, then maxconn
4933 * is used.
4934 */
4935 if (!curproxy->fullconn)
4936 curproxy->fullconn = curproxy->maxconn;
4937
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 /* first, we will invert the servers list order */
4939 newsrv = NULL;
4940 while (curproxy->srv) {
4941 struct server *next;
4942
4943 next = curproxy->srv->next;
4944 curproxy->srv->next = newsrv;
4945 newsrv = curproxy->srv;
4946 if (!next)
4947 break;
4948 curproxy->srv = next;
4949 }
4950
Willy Tarreau20697042007-11-15 23:26:18 +01004951 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004952 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004954 /* We have to initialize the server lookup mechanism depending
4955 * on what LB algorithm was choosen.
4956 */
4957
4958 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4959 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4960 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004961 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4962 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4963 init_server_map(curproxy);
4964 } else {
4965 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4966 fwrr_init_server_groups(curproxy);
4967 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004968 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004969
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004970 case BE_LB_KIND_LC:
4971 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004972 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004973 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004974
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004975 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004976 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4977 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4978 chash_init_server_tree(curproxy);
4979 } else {
4980 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4981 init_server_map(curproxy);
4982 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004983 break;
4984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985
4986 if (curproxy->options & PR_O_LOGASAP)
4987 curproxy->to_log &= ~LW_BYTES;
4988
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004989 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4990 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4991 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4992 proxy_type_str(curproxy), curproxy->id);
4993 err_code |= ERR_WARN;
4994 }
4995
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01004996 if (curproxy->mode != PR_MODE_HTTP) {
4997 int optnum;
4998
4999 if (curproxy->options & PR_O_COOK_ANY) {
5000 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5001 proxy_type_str(curproxy), curproxy->id);
5002 err_code |= ERR_WARN;
5003 }
5004
5005 if (curproxy->uri_auth) {
5006 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5007 proxy_type_str(curproxy), curproxy->id);
5008 err_code |= ERR_WARN;
5009 curproxy->uri_auth = NULL;
5010 }
5011
5012 if (curproxy->options & PR_O_FWDFOR) {
5013 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5014 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5015 err_code |= ERR_WARN;
5016 curproxy->options &= ~PR_O_FWDFOR;
5017 }
5018
5019 if (curproxy->options & PR_O_ORGTO) {
5020 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5021 "originalto", proxy_type_str(curproxy), curproxy->id);
5022 err_code |= ERR_WARN;
5023 curproxy->options &= ~PR_O_ORGTO;
5024 }
5025
5026 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5027 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5028 (curproxy->cap & cfg_opts[optnum].cap) &&
5029 (curproxy->options & cfg_opts[optnum].val)) {
5030 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5031 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5032 err_code |= ERR_WARN;
5033 curproxy->options &= ~cfg_opts[optnum].val;
5034 }
5035 }
5036
5037 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5038 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5039 (curproxy->cap & cfg_opts2[optnum].cap) &&
5040 (curproxy->options2 & cfg_opts2[optnum].val)) {
5041 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5042 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5043 err_code |= ERR_WARN;
5044 curproxy->options2 &= ~cfg_opts2[optnum].val;
5045 }
5046 }
5047 }
5048
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005050 * ensure that we're not cross-dressing a TCP server into HTTP.
5051 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005052 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005053 newsrv = curproxy->srv;
5054 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005055 if (!newsrv->puid) {
5056 /* server ID not set, use automatic numbering with first
5057 * spare entry starting with next_svid.
5058 */
5059 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5060 newsrv->conf.id.key = newsrv->puid = next_id;
5061 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005062 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005063 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005064
Willy Tarreau21d2af32008-02-14 20:25:24 +01005065 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005066 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5067 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005068 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005069 }
5070 newsrv = newsrv->next;
5071 }
5072
5073 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 * If this server supports a maxconn parameter, it needs a dedicated
5075 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005076 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 */
5078 newsrv = curproxy->srv;
5079 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005080 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 /* Only 'minconn' was specified, or it was higher than or equal
5082 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5083 * this will avoid further useless expensive computations.
5084 */
5085 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005086 } else if (newsrv->maxconn && !newsrv->minconn) {
5087 /* minconn was not specified, so we set it to maxconn */
5088 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005089 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005090 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5091 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005092 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
5094
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005095 if (newsrv->trackit) {
5096 struct proxy *px;
5097 struct server *srv;
5098 char *pname, *sname;
5099
5100 pname = newsrv->trackit;
5101 sname = strrchr(pname, '/');
5102
5103 if (sname)
5104 *sname++ = '\0';
5105 else {
5106 sname = pname;
5107 pname = NULL;
5108 }
5109
5110 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005111 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005112 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005113 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5114 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005115 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005116 cfgerr++;
5117 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005118 }
5119 } else
5120 px = curproxy;
5121
5122 srv = findserver(px, sname);
5123 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005124 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5125 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005126 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005127 cfgerr++;
5128 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005129 }
5130
5131 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005132 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005133 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005134 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005135 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005136 cfgerr++;
5137 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005138 }
5139
5140 if (curproxy != px &&
5141 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005142 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005143 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005144 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005145 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005146 cfgerr++;
5147 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005148 }
5149
5150 newsrv->tracked = srv;
5151 newsrv->tracknext = srv->tracknext;
5152 srv->tracknext = newsrv;
5153
5154 free(newsrv->trackit);
5155 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005156 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 newsrv = newsrv->next;
5158 }
5159
Willy Tarreauc1a21672009-08-16 22:37:44 +02005160 if (curproxy->cap & PR_CAP_FE) {
5161 if (curproxy->tcp_req.inspect_delay ||
5162 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5163 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5164
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005165 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005166 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005167 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005168 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005169
5170 /* both TCP and HTTP must check switching rules */
5171 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5172 }
5173
5174 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005175 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005176 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005177 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005178 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005179
Emeric Brunb982a3d2010-01-04 15:45:53 +01005180 /* init table on backend capabilities proxy */
5181 stktable_init(&curproxy->table);
5182
Willy Tarreauc1a21672009-08-16 22:37:44 +02005183 /* If the backend does requires RDP cookie persistence, we have to
5184 * enable the corresponding analyser.
5185 */
5186 if (curproxy->options2 & PR_O2_RDPC_PRST)
5187 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5188 }
5189
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005190 listener = NULL;
5191 while (curproxy->listen) {
5192 struct listener *next;
5193
5194 next = curproxy->listen->next;
5195 curproxy->listen->next = listener;
5196 listener = curproxy->listen;
5197
5198 if (!next)
5199 break;
5200
5201 curproxy->listen = next;
5202 }
5203
Willy Tarreaue6b98942007-10-29 01:09:36 +01005204 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005205 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005206 listener = curproxy->listen;
5207 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005208 if (!listener->luid) {
5209 /* listener ID not set, use automatic numbering with first
5210 * spare entry starting with next_luid.
5211 */
5212 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5213 listener->conf.id.key = listener->luid = next_id;
5214 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005215 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005216 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005217
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005218 /* enable separate counters */
5219 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5220 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5221 if (!listener->name) {
5222 sprintf(trash, "sock-%d", listener->luid);
5223 listener->name = strdup(trash);
5224 }
5225 }
5226
Willy Tarreaue6b98942007-10-29 01:09:36 +01005227 if (curproxy->options & PR_O_TCP_NOLING)
5228 listener->options |= LI_O_NOLINGER;
5229 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005230 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005231 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005232 listener->accept = event_accept;
5233 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005234 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005235 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005236
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005237 /* smart accept mode is automatic in HTTP mode */
5238 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5239 (curproxy->mode == PR_MODE_HTTP &&
5240 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5241 listener->options |= LI_O_NOQUICKACK;
5242
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005243 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005244 listener = listener->next;
5245 }
5246
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 curproxy = curproxy->next;
5248 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005249
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005250 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5251 struct auth_users *curuser;
5252 int g;
5253
5254 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5255 unsigned int group_mask = 0;
5256 char *group = NULL;
5257
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005258 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005259 continue;
5260
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005261 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005262
5263 for (g = 0; g < curuserlist->grpcnt; g++)
5264 if (!strcmp(curuserlist->groups[g], group))
5265 break;
5266
5267 if (g == curuserlist->grpcnt) {
5268 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5269 curuserlist->name, group, curuser->user);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272 }
5273
5274 group_mask |= (1 << g);
5275 }
5276
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005277 free(curuser->u.groups);
5278 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005279 }
5280
5281 for (g = 0; g < curuserlist->grpcnt; g++) {
5282 char *user = NULL;
5283
5284 if (!curuserlist->groupusers[g])
5285 continue;
5286
5287 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5288 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5289 if (!strcmp(curuser->user, user))
5290 break;
5291
5292 if (!curuser) {
5293 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5294 curuserlist->name, user, curuserlist->groups[g]);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005299 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005300 }
5301
5302 free(curuserlist->groupusers[g]);
5303 }
5304
5305 free(curuserlist->groupusers);
5306
5307#ifdef DEBUG_AUTH
5308 for (g = 0; g < curuserlist->grpcnt; g++) {
5309 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5310
5311 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5312 if (curuser->group_mask & (1 << g))
5313 fprintf(stderr, " %s", curuser->user);
5314 }
5315
5316 fprintf(stderr, "\n");
5317 }
5318#endif
5319
5320 }
5321
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005322 /*
5323 * Recount currently required checks.
5324 */
5325
5326 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5327 int optnum;
5328
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005329 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5330 if (curproxy->options & cfg_opts[optnum].val)
5331 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005332
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005333 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5334 if (curproxy->options2 & cfg_opts2[optnum].val)
5335 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005336 }
5337
Willy Tarreaubb925012009-07-23 13:36:36 +02005338 if (cfgerr > 0)
5339 err_code |= ERR_ALERT | ERR_FATAL;
5340 out:
5341 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342}
5343
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005344/*
5345 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5346 * parsing sessions.
5347 */
5348void cfg_register_keywords(struct cfg_kw_list *kwl)
5349{
5350 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5351}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005353/*
5354 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5355 */
5356void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5357{
5358 LIST_DEL(&kwl->list);
5359 LIST_INIT(&kwl->list);
5360}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361
5362/*
5363 * Local variables:
5364 * c-indent-level: 8
5365 * c-basic-offset: 8
5366 * End:
5367 */