blob: 645c631c8cc8db308fd384b3f8cd2e52d877994e [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 Tarreau96839092010-03-29 10:02:24 +02003184 if (newsrv->health)
3185 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 cur_arg += 2;
3187 }
3188 else if (!strcmp(args[cur_arg], "fall")) {
3189 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003190
3191 if (!*args[cur_arg + 1]) {
3192 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3193 file, linenum, args[cur_arg]);
3194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
3196 }
3197
3198 if (newsrv->fall <= 0) {
3199 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3200 file, linenum, args[cur_arg]);
3201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
3203 }
3204
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 cur_arg += 2;
3206 }
3207 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003208 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3209 if (err) {
3210 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3211 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003214 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003215 if (val <= 0) {
3216 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3217 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003220 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003221 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 cur_arg += 2;
3223 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003224 else if (!strcmp(args[cur_arg], "fastinter")) {
3225 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3226 if (err) {
3227 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3228 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003229 err_code |= ERR_ALERT | ERR_FATAL;
3230 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003231 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003232 if (val <= 0) {
3233 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3234 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003237 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003238 newsrv->fastinter = val;
3239 cur_arg += 2;
3240 }
3241 else if (!strcmp(args[cur_arg], "downinter")) {
3242 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3243 if (err) {
3244 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3245 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003248 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003249 if (val <= 0) {
3250 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3251 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003254 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003255 newsrv->downinter = val;
3256 cur_arg += 2;
3257 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003258 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003259 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3260 if (!sk) {
3261 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003266 cur_arg += 2;
3267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 else if (!strcmp(args[cur_arg], "port")) {
3269 newsrv->check_port = atol(args[cur_arg + 1]);
3270 cur_arg += 2;
3271 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003272 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 newsrv->state |= SRV_BACKUP;
3274 cur_arg ++;
3275 }
3276 else if (!strcmp(args[cur_arg], "weight")) {
3277 int w;
3278 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003279 if (w < 0 || w > 256) {
3280 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003285 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 cur_arg += 2;
3287 }
3288 else if (!strcmp(args[cur_arg], "minconn")) {
3289 newsrv->minconn = atol(args[cur_arg + 1]);
3290 cur_arg += 2;
3291 }
3292 else if (!strcmp(args[cur_arg], "maxconn")) {
3293 newsrv->maxconn = atol(args[cur_arg + 1]);
3294 cur_arg += 2;
3295 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003296 else if (!strcmp(args[cur_arg], "maxqueue")) {
3297 newsrv->maxqueue = atol(args[cur_arg + 1]);
3298 cur_arg += 2;
3299 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003300 else if (!strcmp(args[cur_arg], "slowstart")) {
3301 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003302 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003303 if (err) {
3304 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3305 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003308 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003309 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003310 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3311 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003314 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003315 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003316 cur_arg += 2;
3317 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003318 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003319
3320 if (!*args[cur_arg + 1]) {
3321 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3322 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003325 }
3326
3327 newsrv->trackit = strdup(args[cur_arg + 1]);
3328
3329 cur_arg += 2;
3330 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003331 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 global.maxsock++;
3333 do_check = 1;
3334 cur_arg += 1;
3335 }
Willy Tarreau96839092010-03-29 10:02:24 +02003336 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3337 newsrv->state |= SRV_MAINTAIN;
3338 newsrv->state &= ~SRV_RUNNING;
3339 newsrv->health = 0;
3340 cur_arg += 1;
3341 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003342 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003343 if (!strcmp(args[cur_arg + 1], "none"))
3344 newsrv->observe = HANA_OBS_NONE;
3345 else if (!strcmp(args[cur_arg + 1], "layer4"))
3346 newsrv->observe = HANA_OBS_LAYER4;
3347 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3348 if (curproxy->mode != PR_MODE_HTTP) {
3349 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3350 file, linenum, args[cur_arg + 1]);
3351 err_code |= ERR_ALERT;
3352 }
3353 newsrv->observe = HANA_OBS_LAYER7;
3354 }
3355 else {
3356 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3357 "'l4events', 'http-responses' but get '%s'\n",
3358 file, linenum, args[cur_arg], args[cur_arg + 1]);
3359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
3361 }
3362
3363 cur_arg += 2;
3364 }
3365 else if (!strcmp(args[cur_arg], "on-error")) {
3366 if (!strcmp(args[cur_arg + 1], "fastinter"))
3367 newsrv->onerror = HANA_ONERR_FASTINTER;
3368 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3369 newsrv->onerror = HANA_ONERR_FAILCHK;
3370 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3371 newsrv->onerror = HANA_ONERR_SUDDTH;
3372 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3373 newsrv->onerror = HANA_ONERR_MARKDWN;
3374 else {
3375 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3376 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3377 file, linenum, args[cur_arg], args[cur_arg + 1]);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
3381
3382 cur_arg += 2;
3383 }
3384 else if (!strcmp(args[cur_arg], "error-limit")) {
3385 if (!*args[cur_arg + 1]) {
3386 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3387 file, linenum, args[cur_arg]);
3388 err_code |= ERR_ALERT | ERR_FATAL;
3389 goto out;
3390 }
3391
3392 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3393
3394 if (newsrv->consecutive_errors_limit <= 0) {
3395 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3396 file, linenum, args[cur_arg]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003400 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003401 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003402 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003403 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003404 struct sockaddr_in *sk;
3405
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003407#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003408 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003409 file, linenum, "source", "usesrc");
3410#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003411 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003413#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 }
3417 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003418 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3419 if (!sk) {
3420 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
3423 }
3424 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003425
3426 if (port_low != port_high) {
3427 int i;
3428 if (port_low <= 0 || port_low > 65535 ||
3429 port_high <= 0 || port_high > 65535 ||
3430 port_low > port_high) {
3431 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3432 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003435 }
3436 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3437 for (i = 0; i < newsrv->sport_range->size; i++)
3438 newsrv->sport_range->ports[i] = port_low + i;
3439 }
3440
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003442 while (*(args[cur_arg])) {
3443 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003444#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3445#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003446 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3447 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3448 file, linenum, "usesrc", "source");
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 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003452#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003453 if (!*args[cur_arg + 1]) {
3454 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3455 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003458 }
3459 if (!strcmp(args[cur_arg + 1], "client")) {
3460 newsrv->state |= SRV_TPROXY_CLI;
3461 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3462 newsrv->state |= SRV_TPROXY_CIP;
3463 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003464 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3465 if (!sk) {
3466 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
3470 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003471 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003472 }
3473 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003474#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003475 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003476#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003477 cur_arg += 2;
3478 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003479#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003480 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003481 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003484#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3485 } /* "usesrc" */
3486
3487 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3488#ifdef SO_BINDTODEVICE
3489 if (!*args[cur_arg + 1]) {
3490 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003494 }
3495 if (newsrv->iface_name)
3496 free(newsrv->iface_name);
3497
3498 newsrv->iface_name = strdup(args[cur_arg + 1]);
3499 newsrv->iface_len = strlen(newsrv->iface_name);
3500 global.last_checks |= LSTCHK_NETADM;
3501#else
3502 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3503 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003506#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003507 cur_arg += 2;
3508 continue;
3509 }
3510 /* this keyword in not an option of "source" */
3511 break;
3512 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003514 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003515 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3516 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003521 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003522 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003523 file, linenum, newsrv->id);
3524 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003525 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 +01003526 file, linenum);
3527
Willy Tarreau93893792009-07-23 13:19:11 +02003528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 }
3531 }
3532
3533 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003534 if (newsrv->trackit) {
3535 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3536 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003539 }
3540
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003541 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3542 newsrv->check_port = newsrv->check_addr.sin_port;
3543
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3545 newsrv->check_port = realport; /* by default */
3546 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003547 /* not yet valid, because no port was set on
3548 * the server either. We'll check if we have
3549 * a known port on the first listener.
3550 */
3551 struct listener *l;
3552 l = curproxy->listen;
3553 if (l) {
3554 int port;
3555 port = (l->addr.ss_family == AF_INET6)
3556 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3557 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3558 newsrv->check_port = port;
3559 }
3560 }
3561 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3563 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003567
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003568 /* Allocate buffer for partial check results... */
3569 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3570 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3571 err_code |= ERR_ALERT | ERR_ABORT;
3572 goto out;
3573 }
3574
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003575 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 newsrv->state |= SRV_CHECKED;
3577 }
3578
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003579 if (!defsrv) {
3580 if (newsrv->state & SRV_BACKUP)
3581 curproxy->srv_bck++;
3582 else
3583 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003584
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003585 newsrv->prev_state = newsrv->state;
3586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
3588 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003589 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 int facility;
3591
3592 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3593 curproxy->logfac1 = global.logfac1;
3594 curproxy->logsrv1 = global.logsrv1;
3595 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003596 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 curproxy->logfac2 = global.logfac2;
3598 curproxy->logsrv2 = global.logsrv2;
3599 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003600 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 }
3602 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003603 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604
3605 facility = get_log_facility(args[2]);
3606 if (facility < 0) {
3607 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3608 exit(1);
3609 }
3610
3611 level = 7; /* max syslog level = debug */
3612 if (*(args[3])) {
3613 level = get_log_level(args[3]);
3614 if (level < 0) {
3615 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3616 exit(1);
3617 }
3618 }
3619
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003620 minlvl = 0; /* limit syslog level to this level (emerg) */
3621 if (*(args[4])) {
3622 minlvl = get_log_level(args[4]);
3623 if (level < 0) {
3624 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3625 exit(1);
3626 }
3627 }
3628
Robert Tsai81ae1952007-12-05 10:47:29 +01003629 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003630 struct sockaddr_un *sk = str2sun(args[1]);
3631 if (!sk) {
3632 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3633 args[1], (int)sizeof(sk->sun_path) - 1);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003638 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003639 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003640 struct sockaddr_in *sk = str2sa(args[1]);
3641 if (!sk) {
3642 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
3645 }
3646 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003647 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003648 if (!logsrv.u.in.sin_port) {
3649 logsrv.u.in.sin_port =
3650 htons(SYSLOG_PORT);
3651 }
3652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653
3654 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003655 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 curproxy->logfac1 = facility;
3657 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003658 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 }
3660 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003661 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 curproxy->logfac2 = facility;
3663 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003664 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 }
3666 else {
3667 Alert("parsing [%s:%d] : too many syslog servers\n", 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 {
3673 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3674 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 }
3678 }
3679 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003680 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003681 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003682
Willy Tarreau977b8e42006-12-29 14:19:17 +01003683 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003685
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003687 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3688 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003692
3693 /* we must first clear any optional default setting */
3694 curproxy->options &= ~PR_O_TPXY_MASK;
3695 free(curproxy->iface_name);
3696 curproxy->iface_name = NULL;
3697 curproxy->iface_len = 0;
3698
Willy Tarreaud5191e72010-02-09 20:50:45 +01003699 sk = str2sa(args[1]);
3700 if (!sk) {
3701 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
3704 }
3705 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003707
3708 cur_arg = 2;
3709 while (*(args[cur_arg])) {
3710 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003711#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3712#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003713 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3714 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\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#endif
3720 if (!*args[cur_arg + 1]) {
3721 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3722 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003725 }
3726
3727 if (!strcmp(args[cur_arg + 1], "client")) {
3728 curproxy->options |= PR_O_TPXY_CLI;
3729 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3730 curproxy->options |= PR_O_TPXY_CIP;
3731 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003732 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3733 if (!sk) {
3734 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
3737 }
3738 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003739 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003740 }
3741 global.last_checks |= LSTCHK_NETADM;
3742#if !defined(CONFIG_HAP_LINUX_TPROXY)
3743 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003744#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003745#else /* no TPROXY support */
3746 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003747 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003750#endif
3751 cur_arg += 2;
3752 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003753 }
3754
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003755 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3756#ifdef SO_BINDTODEVICE
3757 if (!*args[cur_arg + 1]) {
3758 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3759 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003762 }
3763 if (curproxy->iface_name)
3764 free(curproxy->iface_name);
3765
3766 curproxy->iface_name = strdup(args[cur_arg + 1]);
3767 curproxy->iface_len = strlen(curproxy->iface_name);
3768 global.last_checks |= LSTCHK_NETADM;
3769#else
3770 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3771 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003774#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003775 cur_arg += 2;
3776 continue;
3777 }
3778 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3779 file, linenum, args[0], "inteface", "usesrc");
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 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003784 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3785 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3786 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003791 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3793 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003797
3798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3799 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003800 args[0], args[1], args[2], (const char **)args+3);
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], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3806 ACL_DIR_REQ, ACT_REMOVE, 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], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3813 ACL_DIR_REQ, ACT_DENY, 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], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3820 ACL_DIR_REQ, ACT_PASS, 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 }
3825 else if (!strcmp(args[0], "reqallow")) { /* allow 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_ALLOW, 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 Tarreaubaaee002006-06-26 02:48:02 +02003831 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003832 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3834 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003835 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003837 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003838 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003839 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003840 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3841 ACL_DIR_REQ, ACT_SETBE, 0,
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 }
3846 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003847 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3848 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003849 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003850 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003851 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003854 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3856 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003860
3861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3862 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003863 args[0], args[1], args[2], (const char **)args+3);
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], "reqidel")) { /* delete request header from a 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_REMOVE, 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], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003875 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3876 ACL_DIR_REQ, ACT_DENY, 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], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003882 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3883 ACL_DIR_REQ, ACT_PASS, 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 }
3888 else if (!strcmp(args[0], "reqiallow")) { /* allow 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_ALLOW, 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 Tarreaubaaee002006-06-26 02:48:02 +02003894 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003895 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003896 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3897 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003898 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003899 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003900 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003903 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003904
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 if (curproxy == &defproxy) {
3906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003910 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912
Willy Tarreaubaaee002006-06-26 02:48:02 +02003913 if (*(args[1]) == 0) {
3914 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003918
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003919 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3920 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3921 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3922 file, linenum, args[0]);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925 }
3926 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3927 }
3928 else if (*args[2]) {
3929 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3930 file, linenum, args[0], args[2]);
3931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
3933 }
3934
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003935 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003936 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003937 wl->s = strdup(args[1]);
3938 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003939 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 }
3941 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003942 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003948
Willy Tarreauade5ec42010-01-28 19:33:49 +01003949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3950 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003951 args[0], args[1], args[2], (const char **)args+3);
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], "rspdel")) { /* delete 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_REMOVE, 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], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003963 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3964 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003965 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003966 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
3969 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003970 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3972 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 }
3976
Willy Tarreauade5ec42010-01-28 19:33:49 +01003977 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3978 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003979 args[0], args[1], args[2], (const char **)args+3);
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], "rspidel")) { /* delete 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_REMOVE, 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], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003991 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3992 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003993 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003994 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 }
3997 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003998 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003999
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000 if (curproxy == &defproxy) {
4001 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004005 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004006 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008 if (*(args[1]) == 0) {
4009 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 }
4013
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004014 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4015 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4016 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4017 file, linenum, args[0]);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021 err_code |= warnif_cond_requires_req(cond, file, linenum);
4022 }
4023 else if (*args[2]) {
4024 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4025 file, linenum, args[0], args[2]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
4029
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004030 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004031 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004032 wl->s = strdup(args[1]);
4033 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 }
4035 else if (!strcmp(args[0], "errorloc") ||
4036 !strcmp(args[0], "errorloc302") ||
4037 !strcmp(args[0], "errorloc303")) { /* error location */
4038 int errnum, errlen;
4039 char *err;
4040
Willy Tarreau977b8e42006-12-29 14:19:17 +01004041 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004042 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004043
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004045 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 }
4049
4050 errnum = atol(args[1]);
4051 if (!strcmp(args[0], "errorloc303")) {
4052 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4053 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4054 } else {
4055 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4056 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4057 }
4058
Willy Tarreau0f772532006-12-23 20:51:41 +01004059 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4060 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004061 chunk_destroy(&curproxy->errmsg[rc]);
4062 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004063 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004066
4067 if (rc >= HTTP_ERR_SIZE) {
4068 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4069 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070 free(err);
4071 }
4072 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004073 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4074 int errnum, errlen, fd;
4075 char *err;
4076 struct stat stat;
4077
4078 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004079 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004080
4081 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004082 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004085 }
4086
4087 fd = open(args[2], O_RDONLY);
4088 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4089 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4090 file, linenum, args[2], args[1]);
4091 if (fd >= 0)
4092 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004095 }
4096
Willy Tarreau27a674e2009-08-17 07:23:33 +02004097 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004098 errlen = stat.st_size;
4099 } else {
4100 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004101 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004102 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004103 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004104 }
4105
4106 err = malloc(errlen); /* malloc() must succeed during parsing */
4107 errnum = read(fd, err, errlen);
4108 if (errnum != errlen) {
4109 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4110 file, linenum, args[2], args[1]);
4111 close(fd);
4112 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004115 }
4116 close(fd);
4117
4118 errnum = atol(args[1]);
4119 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4120 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004121 chunk_destroy(&curproxy->errmsg[rc]);
4122 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004123 break;
4124 }
4125 }
4126
4127 if (rc >= HTTP_ERR_SIZE) {
4128 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4129 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004130 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004131 free(err);
4132 }
4133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004135 struct cfg_kw_list *kwl;
4136 int index;
4137
4138 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4139 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4140 if (kwl->kw[index].section != CFG_LISTEN)
4141 continue;
4142 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4143 /* prepare error message just in case */
4144 snprintf(trash, sizeof(trash),
4145 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004146 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4147 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004148 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004151 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004152 else if (rc > 0) {
4153 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_WARN;
4155 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004156 }
Willy Tarreau93893792009-07-23 13:19:11 +02004157 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004158 }
4159 }
4160 }
4161
Willy Tarreau6daf3432008-01-22 16:44:08 +01004162 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 }
Willy Tarreau93893792009-07-23 13:19:11 +02004166 out:
4167 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168}
4169
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004170int
4171cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4172{
4173
4174 int err_code = 0;
4175 const char *err;
4176
4177 if (!strcmp(args[0], "userlist")) { /* new userlist */
4178 struct userlist *newul;
4179
4180 if (!*args[1]) {
4181 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4182 file, linenum, args[0]);
4183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
4185 }
4186
4187 err = invalid_char(args[1]);
4188 if (err) {
4189 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4190 file, linenum, *err, args[0], args[1]);
4191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
4193 }
4194
4195 for (newul = userlist; newul; newul = newul->next)
4196 if (!strcmp(newul->name, args[1])) {
4197 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4198 file, linenum, args[1]);
4199 err_code |= ERR_WARN;
4200 goto out;
4201 }
4202
4203 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4204 if (!newul) {
4205 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4206 err_code |= ERR_ALERT | ERR_ABORT;
4207 goto out;
4208 }
4209
4210 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4211 newul->name = strdup(args[1]);
4212
4213 if (!newul->groupusers | !newul->name) {
4214 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4215 err_code |= ERR_ALERT | ERR_ABORT;
4216 goto out;
4217 }
4218
4219 newul->next = userlist;
4220 userlist = newul;
4221
4222 } else if (!strcmp(args[0], "group")) { /* new group */
4223 int cur_arg, i;
4224 const char *err;
4225
4226 if (!*args[1]) {
4227 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4228 file, linenum, args[0]);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
4231 }
4232
4233 err = invalid_char(args[1]);
4234 if (err) {
4235 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4236 file, linenum, *err, args[0], args[1]);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
4239 }
4240
4241 for(i = 0; i < userlist->grpcnt; i++)
4242 if (!strcmp(userlist->groups[i], args[1])) {
4243 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4244 file, linenum, args[1], userlist->name);
4245 err_code |= ERR_ALERT;
4246 goto out;
4247 }
4248
4249 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4250 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4251 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255
4256 cur_arg = 2;
4257
4258 while (*args[cur_arg]) {
4259 if (!strcmp(args[cur_arg], "users")) {
4260 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4261 cur_arg += 2;
4262 continue;
4263 } else {
4264 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4265 file, linenum, args[0]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269 }
4270
4271 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4272 } else if (!strcmp(args[0], "user")) { /* new user */
4273 struct auth_users *newuser;
4274 int cur_arg;
4275
4276 if (!*args[1]) {
4277 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4278 file, linenum, args[0]);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
4282
4283 for (newuser = userlist->users; newuser; newuser = newuser->next)
4284 if (!strcmp(newuser->user, args[1])) {
4285 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4286 file, linenum, args[1], userlist->name);
4287 err_code |= ERR_ALERT;
4288 goto out;
4289 }
4290
4291 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4292 if (!newuser) {
4293 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4294 err_code |= ERR_ALERT | ERR_ABORT;
4295 goto out;
4296 }
4297
4298 newuser->user = strdup(args[1]);
4299
4300 newuser->next = userlist->users;
4301 userlist->users = newuser;
4302
4303 cur_arg = 2;
4304
4305 while (*args[cur_arg]) {
4306 if (!strcmp(args[cur_arg], "password")) {
4307#ifndef CONFIG_HAP_CRYPT
4308 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4309 file, linenum);
4310 err_code |= ERR_ALERT;
4311#endif
4312 newuser->pass = strdup(args[cur_arg + 1]);
4313 cur_arg += 2;
4314 continue;
4315 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4316 newuser->pass = strdup(args[cur_arg + 1]);
4317 newuser->flags |= AU_O_INSECURE;
4318 cur_arg += 2;
4319 continue;
4320 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004321 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004322 cur_arg += 2;
4323 continue;
4324 } else {
4325 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4326 file, linenum, args[0]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330 }
4331 } else {
4332 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4333 err_code |= ERR_ALERT | ERR_FATAL;
4334 }
4335
4336out:
4337 return err_code;
4338}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339
4340/*
4341 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004342 * Returns the error code, 0 if OK, or any combination of :
4343 * - ERR_ABORT: must abort ASAP
4344 * - ERR_FATAL: we can continue parsing but not start the service
4345 * - ERR_WARN: a warning has been emitted
4346 * - ERR_ALERT: an alert has been emitted
4347 * Only the two first ones can stop processing, the two others are just
4348 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004350int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004352 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 FILE *f;
4354 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004355 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004356 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004357
Willy Tarreaubaaee002006-06-26 02:48:02 +02004358 if ((f=fopen(file,"r")) == NULL)
4359 return -1;
4360
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004361 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004362 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004363 char *end;
4364 char *args[MAX_LINE_ARGS + 1];
4365 char *line = thisline;
4366
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 linenum++;
4368
4369 end = line + strlen(line);
4370
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004371 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4372 /* Check if we reached the limit and the last char is not \n.
4373 * Watch out for the last line without the terminating '\n'!
4374 */
4375 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004376 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004377 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004378 }
4379
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004381 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004382 line++;
4383
4384 arg = 0;
4385 args[arg] = line;
4386
4387 while (*line && arg < MAX_LINE_ARGS) {
4388 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4389 * C equivalent value. Other combinations left unchanged (eg: \1).
4390 */
4391 if (*line == '\\') {
4392 int skip = 0;
4393 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4394 *line = line[1];
4395 skip = 1;
4396 }
4397 else if (line[1] == 'r') {
4398 *line = '\r';
4399 skip = 1;
4400 }
4401 else if (line[1] == 'n') {
4402 *line = '\n';
4403 skip = 1;
4404 }
4405 else if (line[1] == 't') {
4406 *line = '\t';
4407 skip = 1;
4408 }
4409 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004410 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004411 unsigned char hex1, hex2;
4412 hex1 = toupper(line[2]) - '0';
4413 hex2 = toupper(line[3]) - '0';
4414 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4415 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4416 *line = (hex1<<4) + hex2;
4417 skip = 3;
4418 }
4419 else {
4420 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004421 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 }
4423 }
4424 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004425 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426 end -= skip;
4427 }
4428 line++;
4429 }
4430 else if (*line == '#' || *line == '\n' || *line == '\r') {
4431 /* end of string, end of loop */
4432 *line = 0;
4433 break;
4434 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004435 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004437 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004438 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 line++;
4440 args[++arg] = line;
4441 }
4442 else {
4443 line++;
4444 }
4445 }
4446
4447 /* empty line */
4448 if (!**args)
4449 continue;
4450
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004451 if (*line) {
4452 /* we had to stop due to too many args.
4453 * Let's terminate the string, print the offending part then cut the
4454 * last arg.
4455 */
4456 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4457 line++;
4458 *line = '\0';
4459
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004460 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004461 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 args[arg] = line;
4464 }
4465
Willy Tarreau540abe42007-05-02 20:50:16 +02004466 /* zero out remaining args and ensure that at least one entry
4467 * is zeroed out.
4468 */
4469 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470 args[arg] = line;
4471 }
4472
Willy Tarreau3842f002009-06-14 11:39:52 +02004473 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004474 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004475 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004476 for (arg=0; *args[arg+1]; arg++)
4477 args[arg] = args[arg+1]; // shift args after inversion
4478 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004479 else if (!strcmp(args[0], "default")) {
4480 kwm = KWM_DEF;
4481 for (arg=0; *args[arg+1]; arg++)
4482 args[arg] = args[arg+1]; // shift args after inversion
4483 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004484
Willy Tarreau3842f002009-06-14 11:39:52 +02004485 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4486 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004488 }
4489
Willy Tarreau977b8e42006-12-29 14:19:17 +01004490 if (!strcmp(args[0], "listen") ||
4491 !strcmp(args[0], "frontend") ||
4492 !strcmp(args[0], "backend") ||
4493 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004494 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004496 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004497 cursection = strdup(args[0]);
4498 }
4499 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004501 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004502 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004503 } else if (!strcmp(args[0], "userlist")) {
4504 confsect = CFG_USERLIST;
4505 free(cursection);
4506 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 /* else it's a section keyword */
4509
4510 switch (confsect) {
4511 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 break;
4514 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004515 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004517 case CFG_USERLIST:
4518 err_code |= cfg_parse_users(file, linenum, args, kwm);
4519 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004521 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004522 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004524
4525 if (err_code & ERR_ABORT)
4526 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004528 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004529 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004531 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004532}
4533
Willy Tarreaubb925012009-07-23 13:36:36 +02004534/*
4535 * Returns the error code, 0 if OK, or any combination of :
4536 * - ERR_ABORT: must abort ASAP
4537 * - ERR_FATAL: we can continue parsing but not start the service
4538 * - ERR_WARN: a warning has been emitted
4539 * - ERR_ALERT: an alert has been emitted
4540 * Only the two first ones can stop processing, the two others are just
4541 * indicators.
4542 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004543int check_config_validity()
4544{
4545 int cfgerr = 0;
4546 struct proxy *curproxy = NULL;
4547 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004548 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004549 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004550 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551
4552 /*
4553 * Now, check for the integrity of all that we have collected.
4554 */
4555
4556 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004557 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004559 /* first, we will invert the proxy list order */
4560 curproxy = NULL;
4561 while (proxy) {
4562 struct proxy *next;
4563
4564 next = proxy->next;
4565 proxy->next = curproxy;
4566 curproxy = proxy;
4567 if (!next)
4568 break;
4569 proxy = next;
4570 }
4571
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004573 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 }
4577
4578 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004579 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004580 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004581 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004582 unsigned int next_id;
4583
4584 if (!curproxy->uuid) {
4585 /* proxy ID not set, use automatic numbering with first
4586 * spare entry starting with next_pxid.
4587 */
4588 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4589 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4590 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004591 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004592 next_pxid++;
4593
Willy Tarreau55ea7572007-06-17 19:56:27 +02004594
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004596 /* ensure we don't keep listeners uselessly bound */
4597 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 curproxy = curproxy->next;
4599 continue;
4600 }
4601
Willy Tarreauff01a212009-03-15 13:46:16 +01004602 switch (curproxy->mode) {
4603 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004604 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004605 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004606 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4607 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004608 cfgerr++;
4609 }
4610
4611 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004612 Warning("config : servers will be ignored for %s '%s'.\n",
4613 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004614 break;
4615
4616 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004617 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004618 break;
4619
4620 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004621 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004622 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004623 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4624 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004625 cfgerr++;
4626 }
4627 break;
4628 }
4629
4630 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004631 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4632 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 cfgerr++;
4634 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004635
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004636 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004637 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004638 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004639 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4640 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004641 cfgerr++;
4642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004644 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004645 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4646 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004647 cfgerr++;
4648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004650 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004651 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4652 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004653 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004654 }
4655 }
4656 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4657 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4658 /* If no LB algo is set in a backend, and we're not in
4659 * transparent mode, dispatch mode nor proxy mode, we
4660 * want to use balance roundrobin by default.
4661 */
4662 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4663 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 }
4665 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004666
Willy Tarreau82936582007-11-30 15:20:09 +01004667 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4668 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004669 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4670 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004671 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004672 }
4673
Willy Tarreauef781042010-01-27 11:53:01 +01004674 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4675 curproxy->options &= ~PR_O2_CHK_SNDST;
4676 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4677 "send-state", proxy_type_str(curproxy), curproxy->id);
4678 err_code |= ERR_WARN;
4679 }
4680
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004681 /* if a default backend was specified, let's find it */
4682 if (curproxy->defbe.name) {
4683 struct proxy *target;
4684
Alex Williams96532db2009-11-01 21:27:13 -05004685 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004686 if (!target) {
4687 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4688 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004689 cfgerr++;
4690 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004691 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4692 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004693 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004694 } else {
4695 free(curproxy->defbe.name);
4696 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004697 /* we force the backend to be present on at least all of
4698 * the frontend's processes.
4699 */
4700 target->bind_proc = curproxy->bind_proc ?
4701 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 }
4703 }
4704
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004705 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004706 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4707 /* map jump target for ACT_SETBE in req_rep chain */
4708 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004709 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004710 struct proxy *target;
4711
Willy Tarreaua496b602006-12-17 23:15:24 +01004712 if (exp->action != ACT_SETBE)
4713 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004714
Alex Williams96532db2009-11-01 21:27:13 -05004715 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004716 if (!target) {
4717 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4718 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004719 cfgerr++;
4720 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004721 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4722 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004723 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004724 } else {
4725 free((void *)exp->replace);
4726 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004727 /* we force the backend to be present on at least all of
4728 * the frontend's processes.
4729 */
4730 target->bind_proc = curproxy->bind_proc ?
4731 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004732 }
4733 }
4734 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004735
4736 /* find the target proxy for 'use_backend' rules */
4737 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004738 struct proxy *target;
4739
Alex Williams96532db2009-11-01 21:27:13 -05004740 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004741
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004742 if (!target) {
4743 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4744 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004745 cfgerr++;
4746 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004747 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4748 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004749 cfgerr++;
4750 } else {
4751 free((void *)rule->be.name);
4752 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004753 /* we force the backend to be present on at least all of
4754 * the frontend's processes.
4755 */
4756 target->bind_proc = curproxy->bind_proc ?
4757 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004758 }
4759 }
4760
Emeric Brunb982a3d2010-01-04 15:45:53 +01004761 /* find the target table for 'stick' rules */
4762 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4763 struct proxy *target;
4764
Emeric Brun1d33b292010-01-04 15:47:17 +01004765 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4766 if (mrule->flags & STK_IS_STORE)
4767 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4768
Emeric Brunb982a3d2010-01-04 15:45:53 +01004769 if (mrule->table.name)
4770 target = findproxy(mrule->table.name, PR_CAP_BE);
4771 else
4772 target = curproxy;
4773
4774 if (!target) {
4775 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4776 curproxy->id, mrule->table.name);
4777 cfgerr++;
4778 }
4779 else if (target->table.size == 0) {
4780 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4781 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4782 cfgerr++;
4783 }
4784 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4785 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4786 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4787 cfgerr++;
4788 }
4789 else {
4790 free((void *)mrule->table.name);
4791 mrule->table.t = &(target->table);
4792 }
4793 }
4794
4795 /* find the target table for 'store response' rules */
4796 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4797 struct proxy *target;
4798
Emeric Brun1d33b292010-01-04 15:47:17 +01004799 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4800
Emeric Brunb982a3d2010-01-04 15:45:53 +01004801 if (mrule->table.name)
4802 target = findproxy(mrule->table.name, PR_CAP_BE);
4803 else
4804 target = curproxy;
4805
4806 if (!target) {
4807 Alert("Proxy '%s': unable to find store table '%s'.\n",
4808 curproxy->id, mrule->table.name);
4809 cfgerr++;
4810 }
4811 else if (target->table.size == 0) {
4812 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4813 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4814 cfgerr++;
4815 }
4816 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4817 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4818 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4819 cfgerr++;
4820 }
4821 else {
4822 free((void *)mrule->table.name);
4823 mrule->table.t = &(target->table);
4824 }
4825 }
4826
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004827 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4828 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004829 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4830 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4831 "proxy", curproxy->id);
4832 cfgerr++;
4833 goto out_uri_auth_compat;
4834 }
4835
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004836 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004837 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004838 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004839 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004840
Willy Tarreau95fa4692010-02-01 13:05:50 +01004841 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4842 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004843
4844 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004845 uri_auth_compat_req[i++] = "realm";
4846 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4847 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004848
Willy Tarreau95fa4692010-02-01 13:05:50 +01004849 uri_auth_compat_req[i++] = "unless";
4850 uri_auth_compat_req[i++] = "{";
4851 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4852 uri_auth_compat_req[i++] = "}";
4853 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004854
Willy Tarreau95fa4692010-02-01 13:05:50 +01004855 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4856 if (!req_acl) {
4857 cfgerr++;
4858 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004859 }
4860
Willy Tarreau95fa4692010-02-01 13:05:50 +01004861 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4862
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004863 if (curproxy->uri_auth->auth_realm) {
4864 free(curproxy->uri_auth->auth_realm);
4865 curproxy->uri_auth->auth_realm = NULL;
4866 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004867
4868 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004869 }
4870out_uri_auth_compat:
4871
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004872 cfgerr += acl_find_targets(curproxy);
4873
Willy Tarreau2738a142006-07-08 17:28:09 +02004874 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004875 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004876 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004877 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004878 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004879 " | While not properly invalid, you will certainly encounter various problems\n"
4880 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004881 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004882 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004883 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004884 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004885
Willy Tarreau1fa31262007-12-03 00:36:16 +01004886 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4887 * We must still support older configurations, so let's find out whether those
4888 * parameters have been set or must be copied from contimeouts.
4889 */
4890 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004891 if (!curproxy->timeout.tarpit ||
4892 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004893 /* tarpit timeout not set. We search in the following order:
4894 * default.tarpit, curr.connect, default.connect.
4895 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004896 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004897 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004898 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004899 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004900 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004901 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004902 }
4903 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004904 (!curproxy->timeout.queue ||
4905 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004906 /* queue timeout not set. We search in the following order:
4907 * default.queue, curr.connect, default.connect.
4908 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004909 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004910 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004911 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004912 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004913 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004914 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004915 }
4916 }
4917
Willy Tarreauf3c69202006-07-09 16:42:34 +02004918 if (curproxy->options & PR_O_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01004919 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
4920 curproxy->check_req = (char *)malloc(curproxy->check_len);
4921 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02004922 }
4923
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004924 /* The small pools required for the capture lists */
4925 if (curproxy->nb_req_cap)
4926 curproxy->req_cap_pool = create_pool("ptrcap",
4927 curproxy->nb_req_cap * sizeof(char *),
4928 MEM_F_SHARED);
4929 if (curproxy->nb_rsp_cap)
4930 curproxy->rsp_cap_pool = create_pool("ptrcap",
4931 curproxy->nb_rsp_cap * sizeof(char *),
4932 MEM_F_SHARED);
4933
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004934 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4935 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4936 MEM_F_SHARED);
4937
Willy Tarreau86034312006-12-29 00:10:33 +01004938 /* for backwards compatibility with "listen" instances, if
4939 * fullconn is not set but maxconn is set, then maxconn
4940 * is used.
4941 */
4942 if (!curproxy->fullconn)
4943 curproxy->fullconn = curproxy->maxconn;
4944
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 /* first, we will invert the servers list order */
4946 newsrv = NULL;
4947 while (curproxy->srv) {
4948 struct server *next;
4949
4950 next = curproxy->srv->next;
4951 curproxy->srv->next = newsrv;
4952 newsrv = curproxy->srv;
4953 if (!next)
4954 break;
4955 curproxy->srv = next;
4956 }
4957
Willy Tarreau20697042007-11-15 23:26:18 +01004958 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004959 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004961 /* We have to initialize the server lookup mechanism depending
4962 * on what LB algorithm was choosen.
4963 */
4964
4965 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4966 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4967 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004968 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4969 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4970 init_server_map(curproxy);
4971 } else {
4972 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4973 fwrr_init_server_groups(curproxy);
4974 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004975 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004976
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004977 case BE_LB_KIND_LC:
4978 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004979 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004980 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004981
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004982 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004983 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4984 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4985 chash_init_server_tree(curproxy);
4986 } else {
4987 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4988 init_server_map(curproxy);
4989 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004990 break;
4991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992
4993 if (curproxy->options & PR_O_LOGASAP)
4994 curproxy->to_log &= ~LW_BYTES;
4995
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004996 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4997 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4998 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4999 proxy_type_str(curproxy), curproxy->id);
5000 err_code |= ERR_WARN;
5001 }
5002
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005003 if (curproxy->mode != PR_MODE_HTTP) {
5004 int optnum;
5005
5006 if (curproxy->options & PR_O_COOK_ANY) {
5007 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5008 proxy_type_str(curproxy), curproxy->id);
5009 err_code |= ERR_WARN;
5010 }
5011
5012 if (curproxy->uri_auth) {
5013 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5014 proxy_type_str(curproxy), curproxy->id);
5015 err_code |= ERR_WARN;
5016 curproxy->uri_auth = NULL;
5017 }
5018
5019 if (curproxy->options & PR_O_FWDFOR) {
5020 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5021 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5022 err_code |= ERR_WARN;
5023 curproxy->options &= ~PR_O_FWDFOR;
5024 }
5025
5026 if (curproxy->options & PR_O_ORGTO) {
5027 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5028 "originalto", proxy_type_str(curproxy), curproxy->id);
5029 err_code |= ERR_WARN;
5030 curproxy->options &= ~PR_O_ORGTO;
5031 }
5032
5033 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5034 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5035 (curproxy->cap & cfg_opts[optnum].cap) &&
5036 (curproxy->options & cfg_opts[optnum].val)) {
5037 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5038 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5039 err_code |= ERR_WARN;
5040 curproxy->options &= ~cfg_opts[optnum].val;
5041 }
5042 }
5043
5044 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5045 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5046 (curproxy->cap & cfg_opts2[optnum].cap) &&
5047 (curproxy->options2 & cfg_opts2[optnum].val)) {
5048 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5049 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5050 err_code |= ERR_WARN;
5051 curproxy->options2 &= ~cfg_opts2[optnum].val;
5052 }
5053 }
5054 }
5055
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005057 * ensure that we're not cross-dressing a TCP server into HTTP.
5058 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005059 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005060 newsrv = curproxy->srv;
5061 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005062 if (!newsrv->puid) {
5063 /* server ID not set, use automatic numbering with first
5064 * spare entry starting with next_svid.
5065 */
5066 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5067 newsrv->conf.id.key = newsrv->puid = next_id;
5068 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005069 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005070 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005071
Willy Tarreau21d2af32008-02-14 20:25:24 +01005072 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005073 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5074 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005075 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005076 }
5077 newsrv = newsrv->next;
5078 }
5079
5080 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 * If this server supports a maxconn parameter, it needs a dedicated
5082 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005083 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 */
5085 newsrv = curproxy->srv;
5086 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005087 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 /* Only 'minconn' was specified, or it was higher than or equal
5089 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5090 * this will avoid further useless expensive computations.
5091 */
5092 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005093 } else if (newsrv->maxconn && !newsrv->minconn) {
5094 /* minconn was not specified, so we set it to maxconn */
5095 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005096 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005097 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5098 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005099 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 }
5101
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005102 if (newsrv->trackit) {
5103 struct proxy *px;
5104 struct server *srv;
5105 char *pname, *sname;
5106
5107 pname = newsrv->trackit;
5108 sname = strrchr(pname, '/');
5109
5110 if (sname)
5111 *sname++ = '\0';
5112 else {
5113 sname = pname;
5114 pname = NULL;
5115 }
5116
5117 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005118 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005119 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005120 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5121 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005122 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005123 cfgerr++;
5124 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005125 }
5126 } else
5127 px = curproxy;
5128
5129 srv = findserver(px, sname);
5130 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005131 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5132 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005133 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005134 cfgerr++;
5135 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005136 }
5137
5138 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005139 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005140 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005141 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005142 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005143 cfgerr++;
5144 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005145 }
5146
5147 if (curproxy != px &&
5148 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005149 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005150 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005151 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005152 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005153 cfgerr++;
5154 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005155 }
5156
5157 newsrv->tracked = srv;
5158 newsrv->tracknext = srv->tracknext;
5159 srv->tracknext = newsrv;
5160
5161 free(newsrv->trackit);
5162 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005163 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 newsrv = newsrv->next;
5165 }
5166
Willy Tarreauc1a21672009-08-16 22:37:44 +02005167 if (curproxy->cap & PR_CAP_FE) {
5168 if (curproxy->tcp_req.inspect_delay ||
5169 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5170 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5171
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005172 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005173 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005174 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005175 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005176
5177 /* both TCP and HTTP must check switching rules */
5178 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5179 }
5180
5181 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005182 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005183 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005184 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005185 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005186
Emeric Brunb982a3d2010-01-04 15:45:53 +01005187 /* init table on backend capabilities proxy */
5188 stktable_init(&curproxy->table);
5189
Willy Tarreauc1a21672009-08-16 22:37:44 +02005190 /* If the backend does requires RDP cookie persistence, we have to
5191 * enable the corresponding analyser.
5192 */
5193 if (curproxy->options2 & PR_O2_RDPC_PRST)
5194 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5195 }
5196
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005197 listener = NULL;
5198 while (curproxy->listen) {
5199 struct listener *next;
5200
5201 next = curproxy->listen->next;
5202 curproxy->listen->next = listener;
5203 listener = curproxy->listen;
5204
5205 if (!next)
5206 break;
5207
5208 curproxy->listen = next;
5209 }
5210
Willy Tarreaue6b98942007-10-29 01:09:36 +01005211 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005212 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005213 listener = curproxy->listen;
5214 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005215 if (!listener->luid) {
5216 /* listener ID not set, use automatic numbering with first
5217 * spare entry starting with next_luid.
5218 */
5219 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5220 listener->conf.id.key = listener->luid = next_id;
5221 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005222 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005223 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005224
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005225 /* enable separate counters */
5226 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5227 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5228 if (!listener->name) {
5229 sprintf(trash, "sock-%d", listener->luid);
5230 listener->name = strdup(trash);
5231 }
5232 }
5233
Willy Tarreaue6b98942007-10-29 01:09:36 +01005234 if (curproxy->options & PR_O_TCP_NOLING)
5235 listener->options |= LI_O_NOLINGER;
5236 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005237 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005238 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005239 listener->accept = event_accept;
5240 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005241 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005242 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005243
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005244 /* smart accept mode is automatic in HTTP mode */
5245 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5246 (curproxy->mode == PR_MODE_HTTP &&
5247 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5248 listener->options |= LI_O_NOQUICKACK;
5249
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005250 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005251 listener = listener->next;
5252 }
5253
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 curproxy = curproxy->next;
5255 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005256
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005257 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5258 struct auth_users *curuser;
5259 int g;
5260
5261 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5262 unsigned int group_mask = 0;
5263 char *group = NULL;
5264
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005265 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005266 continue;
5267
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005268 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005269
5270 for (g = 0; g < curuserlist->grpcnt; g++)
5271 if (!strcmp(curuserlist->groups[g], group))
5272 break;
5273
5274 if (g == curuserlist->grpcnt) {
5275 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5276 curuserlist->name, group, curuser->user);
5277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
5279 }
5280
5281 group_mask |= (1 << g);
5282 }
5283
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005284 free(curuser->u.groups);
5285 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005286 }
5287
5288 for (g = 0; g < curuserlist->grpcnt; g++) {
5289 char *user = NULL;
5290
5291 if (!curuserlist->groupusers[g])
5292 continue;
5293
5294 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5295 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5296 if (!strcmp(curuser->user, user))
5297 break;
5298
5299 if (!curuser) {
5300 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5301 curuserlist->name, user, curuserlist->groups[g]);
5302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 }
5305
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005306 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005307 }
5308
5309 free(curuserlist->groupusers[g]);
5310 }
5311
5312 free(curuserlist->groupusers);
5313
5314#ifdef DEBUG_AUTH
5315 for (g = 0; g < curuserlist->grpcnt; g++) {
5316 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5317
5318 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5319 if (curuser->group_mask & (1 << g))
5320 fprintf(stderr, " %s", curuser->user);
5321 }
5322
5323 fprintf(stderr, "\n");
5324 }
5325#endif
5326
5327 }
5328
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005329 /*
5330 * Recount currently required checks.
5331 */
5332
5333 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5334 int optnum;
5335
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005336 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5337 if (curproxy->options & cfg_opts[optnum].val)
5338 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005339
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005340 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5341 if (curproxy->options2 & cfg_opts2[optnum].val)
5342 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005343 }
5344
Willy Tarreaubb925012009-07-23 13:36:36 +02005345 if (cfgerr > 0)
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 out:
5348 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349}
5350
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005351/*
5352 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5353 * parsing sessions.
5354 */
5355void cfg_register_keywords(struct cfg_kw_list *kwl)
5356{
5357 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5358}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005360/*
5361 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5362 */
5363void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5364{
5365 LIST_DEL(&kwl->list);
5366 LIST_INIT(&kwl->list);
5367}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368
5369/*
5370 * Local variables:
5371 * c-indent-level: 8
5372 * c-basic-offset: 8
5373 * End:
5374 */