blob: 9868b05354e361f7cd33f26aa1a7530e226d61a0 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020043#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020045#include <proto/lb_fwlc.h>
46#include <proto/lb_fwrr.h>
47#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020049#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010050#include <proto/protocols.h>
51#include <proto/proto_tcp.h>
52#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010053#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010055#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/task.h>
57
58
Willy Tarreauf3c69202006-07-09 16:42:34 +020059/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
60 * ssl-hello-chk option to ensure that the remote server speaks SSL.
61 *
62 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
63 */
64const char sslv3_client_hello_pkt[] = {
65 "\x16" /* ContentType : 0x16 = Hanshake */
66 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
67 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
68 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
69 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
70 "\x03\x00" /* Hello Version : 0x0300 = v3 */
71 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
72 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
73 "\x00" /* Session ID length : empty (no session ID) */
74 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
75 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
76 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
77 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
78 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
79 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
80 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
81 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
82 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
83 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
84 "\x00\x38" "\x00\x39" "\x00\x3A"
85 "\x01" /* Compression Length : 0x01 = 1 byte for types */
86 "\x00" /* Compression Type : 0x00 = NULL compression */
87};
88
Willy Tarreau3842f002009-06-14 11:39:52 +020089/* various keyword modifiers */
90enum kw_mod {
91 KWM_STD = 0, /* normal */
92 KWM_NO, /* "no" prefixed before the keyword */
93 KWM_DEF, /* "default" prefixed before the keyword */
94};
95
Willy Tarreau13943ab2006-12-31 00:24:10 +010096/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010097struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010098 const char *name;
99 unsigned int val;
100 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100101 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100102};
103
104/* proxy->options */
105static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100107 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100108 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100111 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
112 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
113 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
114 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
115 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
116 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
117 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
118 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100120 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
121 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100123 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100124#endif
125
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100126 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127};
128
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100129/* proxy->options2 */
130static const struct cfg_opt cfg_opts2[] =
131{
132#ifdef CONFIG_HAP_LINUX_SPLICE
133 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
134 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
135 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
136#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200137 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
138 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200139 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
140 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200141 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200142 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200143 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200144 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200145 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146 { NULL, 0, 0, 0 }
147};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200148
Willy Tarreau6daf3432008-01-22 16:44:08 +0100149static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200150static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
151int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100152int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200153
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200154/* List head of all known configuration keywords */
155static struct cfg_kw_list cfg_keywords = {
156 .list = LIST_HEAD_INIT(cfg_keywords.list)
157};
158
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159/*
160 * converts <str> to a list of listeners which are dynamically allocated.
161 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
162 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
163 * - <port> is a numerical port from 1 to 65535 ;
164 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
165 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200166 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200168static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169{
170 struct listener *l;
171 char *c, *next, *range, *dupstr;
172 int port, end;
173
174 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200175
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176 while (next && *next) {
177 struct sockaddr_storage ss;
178
179 str = next;
180 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100181 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 *next++ = 0;
183 }
184
185 /* 2) look for the addr/port delimiter, it's the last colon. */
186 if ((range = strrchr(str, ':')) == NULL) {
187 Alert("Missing port number: '%s'\n", str);
188 goto fail;
189 }
190
191 *range++ = 0;
192
193 if (strrchr(str, ':') != NULL) {
194 /* IPv6 address contains ':' */
195 memset(&ss, 0, sizeof(ss));
196 ss.ss_family = AF_INET6;
197
198 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
199 Alert("Invalid server address: '%s'\n", str);
200 goto fail;
201 }
202 }
203 else {
204 memset(&ss, 0, sizeof(ss));
205 ss.ss_family = AF_INET;
206
207 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
208 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
209 }
210 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
211 struct hostent *he;
212
213 if ((he = gethostbyname(str)) == NULL) {
214 Alert("Invalid server name: '%s'\n", str);
215 goto fail;
216 }
217 else
218 ((struct sockaddr_in *)&ss)->sin_addr =
219 *(struct in_addr *) *(he->h_addr_list);
220 }
221 }
222
223 /* 3) look for the port-end delimiter */
224 if ((c = strchr(range, '-')) != NULL) {
225 *c++ = 0;
226 end = atol(c);
227 }
228 else {
229 end = atol(range);
230 }
231
232 port = atol(range);
233
234 if (port < 1 || port > 65535) {
235 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
240 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
241 goto fail;
242 }
243
244 for (; port <= end; port++) {
245 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200246 l->next = curproxy->listen;
247 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
249 l->fd = -1;
250 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100251 l->state = LI_INIT;
252
253 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100255 tcpv6_add_listener(l);
256 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100258 tcpv4_add_listener(l);
259 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260
Willy Tarreaue6b98942007-10-29 01:09:36 +0100261 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 } /* end for(port) */
263 } /* end while(next) */
264 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200265 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 fail:
267 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200268 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269}
270
Willy Tarreau977b8e42006-12-29 14:19:17 +0100271/*
272 * Sends a warning if proxy <proxy> does not have at least one of the
273 * capabilities in <cap>. An optionnal <hint> may be added at the end
274 * of the warning to help the user. Returns 1 if a warning was emitted
275 * or 0 if the condition is valid.
276 */
277int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
278{
279 char *msg;
280
281 switch (cap) {
282 case PR_CAP_BE: msg = "no backend"; break;
283 case PR_CAP_FE: msg = "no frontend"; break;
284 case PR_CAP_RS: msg = "no ruleset"; break;
285 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
286 default: msg = "not enough"; break;
287 }
288
289 if (!(proxy->cap & cap)) {
290 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100291 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292 return 1;
293 }
294 return 0;
295}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau61d18892009-03-31 10:49:21 +0200297/* Report a warning if a rule is placed after a 'block' rule.
298 * Return 1 if the warning has been emitted, otherwise 0.
299 */
300int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
301{
302 if (!LIST_ISEMPTY(&proxy->block_cond)) {
303 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
304 file, line, arg);
305 return 1;
306 }
307 return 0;
308}
309
310/* Report a warning if a rule is placed after a reqrewrite rule.
311 * Return 1 if the warning has been emitted, otherwise 0.
312 */
313int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
314{
315 if (proxy->req_exp) {
316 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
317 file, line, arg);
318 return 1;
319 }
320 return 0;
321}
322
323/* Report a warning if a rule is placed after a reqadd rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
327{
328 if (proxy->nb_reqadd) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
336/* Report a warning if a rule is placed after a redirect rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
339int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
340{
341 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a 'use_backend' rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
352int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
353{
354 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* report a warning if a block rule is dangerously placed */
363int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
364{
365 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
366 warnif_rule_after_reqadd(proxy, file, line, arg) ||
367 warnif_rule_after_redirect(proxy, file, line, arg) ||
368 warnif_rule_after_use_backend(proxy, file, line, arg);
369}
370
371/* report a warning if a reqxxx rule is dangerously placed */
372int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
373{
374 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
375 warnif_rule_after_redirect(proxy, file, line, arg) ||
376 warnif_rule_after_use_backend(proxy, file, line, arg);
377}
378
379/* report a warning if a reqadd rule is dangerously placed */
380int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
381{
382 return warnif_rule_after_redirect(proxy, file, line, arg) ||
383 warnif_rule_after_use_backend(proxy, file, line, arg);
384}
385
Willy Tarreaubaaee002006-06-26 02:48:02 +0200386/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200387 * parse a line in a <global> section. Returns the error code, 0 if OK, or
388 * any combination of :
389 * - ERR_ABORT: must abort ASAP
390 * - ERR_FATAL: we can continue parsing but not start the service
391 * - ERR_WARN: a warning has been emitted
392 * - ERR_ALERT: an alert has been emitted
393 * Only the two first ones can stop processing, the two others are just
394 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200395 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200396int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200397{
Willy Tarreau058e9072009-07-20 09:30:05 +0200398 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200399
400 if (!strcmp(args[0], "global")) { /* new section */
401 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200403 }
404 else if (!strcmp(args[0], "daemon")) {
405 global.mode |= MODE_DAEMON;
406 }
407 else if (!strcmp(args[0], "debug")) {
408 global.mode |= MODE_DEBUG;
409 }
410 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100411 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200412 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200413 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100414 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200415 }
416 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100417 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200419 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100420 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200421 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100422 else if (!strcmp(args[0], "nosplice")) {
423 global.tune.options &= ~GTUNE_USE_SPLICE;
424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200425 else if (!strcmp(args[0], "quiet")) {
426 global.mode |= MODE_QUIET;
427 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200428 else if (!strcmp(args[0], "tune.maxpollevents")) {
429 if (global.tune.maxpollevents != 0) {
430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200431 err_code |= ERR_ALERT;
432 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200433 }
434 if (*(args[1]) == 0) {
435 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200436 err_code |= ERR_ALERT | ERR_FATAL;
437 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200438 }
439 global.tune.maxpollevents = atol(args[1]);
440 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100441 else if (!strcmp(args[0], "tune.maxaccept")) {
442 if (global.tune.maxaccept != 0) {
443 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200444 err_code |= ERR_ALERT;
445 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100446 }
447 if (*(args[1]) == 0) {
448 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200449 err_code |= ERR_ALERT | ERR_FATAL;
450 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100451 }
452 global.tune.maxaccept = atol(args[1]);
453 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200454 else if (!strcmp(args[0], "tune.bufsize")) {
455 if (*(args[1]) == 0) {
456 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
457 err_code |= ERR_ALERT | ERR_FATAL;
458 goto out;
459 }
460 global.tune.bufsize = atol(args[1]);
461 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
462 global.tune.maxrewrite = global.tune.bufsize / 2;
463 }
464 else if (!strcmp(args[0], "tune.maxrewrite")) {
465 if (*(args[1]) == 0) {
466 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
467 err_code |= ERR_ALERT | ERR_FATAL;
468 goto out;
469 }
470 global.tune.maxrewrite = atol(args[1]);
471 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
472 global.tune.maxrewrite = global.tune.bufsize / 2;
473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 else if (!strcmp(args[0], "uid")) {
475 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200476 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200477 err_code |= ERR_ALERT;
478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
480 if (*(args[1]) == 0) {
481 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 err_code |= ERR_ALERT | ERR_FATAL;
483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200484 }
485 global.uid = atol(args[1]);
486 }
487 else if (!strcmp(args[0], "gid")) {
488 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200489 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT;
491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492 }
493 if (*(args[1]) == 0) {
494 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200495 err_code |= ERR_ALERT | ERR_FATAL;
496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 }
498 global.gid = atol(args[1]);
499 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200500 /* user/group name handling */
501 else if (!strcmp(args[0], "user")) {
502 struct passwd *ha_user;
503 if (global.uid != 0) {
504 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT;
506 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200507 }
508 errno = 0;
509 ha_user = getpwnam(args[1]);
510 if (ha_user != NULL) {
511 global.uid = (int)ha_user->pw_uid;
512 }
513 else {
514 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 +0200515 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200516 }
517 }
518 else if (!strcmp(args[0], "group")) {
519 struct group *ha_group;
520 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200521 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200522 err_code |= ERR_ALERT;
523 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200524 }
525 errno = 0;
526 ha_group = getgrnam(args[1]);
527 if (ha_group != NULL) {
528 global.gid = (int)ha_group->gr_gid;
529 }
530 else {
531 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 +0200532 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200533 }
534 }
535 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200536 else if (!strcmp(args[0], "nbproc")) {
537 if (global.nbproc != 0) {
538 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT;
540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541 }
542 if (*(args[1]) == 0) {
543 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 }
547 global.nbproc = atol(args[1]);
548 }
549 else if (!strcmp(args[0], "maxconn")) {
550 if (global.maxconn != 0) {
551 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT;
553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554 }
555 if (*(args[1]) == 0) {
556 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200557 err_code |= ERR_ALERT | ERR_FATAL;
558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 }
560 global.maxconn = atol(args[1]);
561#ifdef SYSTEM_MAXCONN
562 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
563 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);
564 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200565 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 }
567#endif /* SYSTEM_MAXCONN */
568 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100569 else if (!strcmp(args[0], "maxpipes")) {
570 if (global.maxpipes != 0) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200572 err_code |= ERR_ALERT;
573 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100579 }
580 global.maxpipes = atol(args[1]);
581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 else if (!strcmp(args[0], "ulimit-n")) {
583 if (global.rlimit_nofile != 0) {
584 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200585 err_code |= ERR_ALERT;
586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 }
593 global.rlimit_nofile = atol(args[1]);
594 }
595 else if (!strcmp(args[0], "chroot")) {
596 if (global.chroot != NULL) {
597 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 }
606 global.chroot = strdup(args[1]);
607 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200608 else if (!strcmp(args[0], "description")) {
609 int i, len=0;
610 char *d;
611
612 if (!*args[1]) {
613 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
614 file, linenum, args[0]);
615 err_code |= ERR_ALERT | ERR_FATAL;
616 goto out;
617 }
618
619 for(i=1; *args[i]; i++)
620 len += strlen(args[i])+1;
621
622 if (global.desc)
623 free(global.desc);
624
625 global.desc = d = (char *)calloc(1, len);
626
627 d += sprintf(d, "%s", args[1]);
628 for(i=2; *args[i]; i++)
629 d += sprintf(d, " %s", args[i]);
630 }
631 else if (!strcmp(args[0], "node")) {
632 int i;
633 char c;
634
635 for (i=0; args[1][i]; i++) {
636 c = args[1][i];
637 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
638 break;
639 }
640
641 if (!i || args[1][i]) {
642 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
643 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
644 file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648
649 if (global.node)
650 free(global.node);
651
652 global.node = strdup(args[1]);
653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 else if (!strcmp(args[0], "pidfile")) {
655 if (global.pidfile != NULL) {
656 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200657 err_code |= ERR_ALERT;
658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 }
665 global.pidfile = strdup(args[1]);
666 }
667 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100668 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200669 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670
671 if (*(args[1]) == 0 || *(args[2]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676
677 facility = get_log_facility(args[2]);
678 if (facility < 0) {
679 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683
684 level = 7; /* max syslog level = debug */
685 if (*(args[3])) {
686 level = get_log_level(args[3]);
687 if (level < 0) {
688 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200689 err_code |= ERR_ALERT | ERR_FATAL;
690 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 }
692 }
693
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200694 minlvl = 0; /* limit syslog level to this level (emerg) */
695 if (*(args[4])) {
696 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200698 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200701 }
702 }
703
Robert Tsai81ae1952007-12-05 10:47:29 +0100704 if (args[1][0] == '/') {
705 logsrv.u.addr.sa_family = AF_UNIX;
706 logsrv.u.un = *str2sun(args[1]);
707 } else {
708 logsrv.u.addr.sa_family = AF_INET;
709 logsrv.u.in = *str2sa(args[1]);
710 if (!logsrv.u.in.sin_port)
711 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713
714 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100715 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 global.logfac1 = facility;
717 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200718 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 }
720 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100721 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722 global.logfac2 = facility;
723 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200724 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200725 }
726 else {
727 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200728 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200730 }
731 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
732 if (global.spread_checks != 0) {
733 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT;
735 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200736 }
737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200741 }
742 global.spread_checks = atol(args[1]);
743 if (global.spread_checks < 0 || global.spread_checks > 50) {
744 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200749 struct cfg_kw_list *kwl;
750 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200751 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200752
753 list_for_each_entry(kwl, &cfg_keywords.list, list) {
754 for (index = 0; kwl->kw[index].kw != NULL; index++) {
755 if (kwl->kw[index].section != CFG_GLOBAL)
756 continue;
757 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
758 /* prepare error message just in case */
759 snprintf(trash, sizeof(trash),
760 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200761 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
762 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200763 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200764 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200765 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200766 else if (rc > 0) {
767 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_WARN;
769 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200770 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200772 }
773 }
774 }
775
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200777 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200779
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 out:
781 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782}
783
784
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200785void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786{
787 memset(&defproxy, 0, sizeof(defproxy));
788 defproxy.mode = PR_MODE_TCP;
789 defproxy.state = PR_STNEW;
790 defproxy.maxconn = cfg_maxpconn;
791 defproxy.conn_retries = CONN_RETRIES;
792 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200793
794 LIST_INIT(&defproxy.pendconns);
795 LIST_INIT(&defproxy.acl);
796 LIST_INIT(&defproxy.block_cond);
797 LIST_INIT(&defproxy.mon_fail_cond);
798 LIST_INIT(&defproxy.switching_rules);
799
Willy Tarreau3a70f942008-02-15 11:15:34 +0100800 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801}
802
803/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100804 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200805 * Returns the error code, 0 if OK, or any combination of :
806 * - ERR_ABORT: must abort ASAP
807 * - ERR_FATAL: we can continue parsing but not start the service
808 * - ERR_WARN: a warning has been emitted
809 * - ERR_ALERT: an alert has been emitted
810 * Only the two first ones can stop processing, the two others are just
811 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200813int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814{
815 static struct proxy *curproxy = NULL;
816 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200817 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100818 int rc;
819 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200820 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821
Willy Tarreau977b8e42006-12-29 14:19:17 +0100822 if (!strcmp(args[0], "listen"))
823 rc = PR_CAP_LISTEN;
824 else if (!strcmp(args[0], "frontend"))
825 rc = PR_CAP_FE | PR_CAP_RS;
826 else if (!strcmp(args[0], "backend"))
827 rc = PR_CAP_BE | PR_CAP_RS;
828 else if (!strcmp(args[0], "ruleset"))
829 rc = PR_CAP_RS;
830 else
831 rc = PR_CAP_NONE;
832
833 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 if (!*args[1]) {
835 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
836 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
837 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200838 err_code |= ERR_ALERT | ERR_ABORT;
839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200841
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100842 err = invalid_char(args[1]);
843 if (err) {
844 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
845 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200846 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100847 }
848
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200849 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
850 /*
851 * If there are two proxies with the same name only following
852 * combinations are allowed:
853 *
854 * listen backend frontend ruleset
855 * listen - - - -
856 * backend - - OK -
857 * frontend - OK - -
858 * ruleset - - - -
859 */
860
861 if (!strcmp(curproxy->id, args[1]) &&
862 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
863 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200864 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
865 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
866 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200867 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200868 }
869 }
870
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
872 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200873 err_code |= ERR_ALERT | ERR_ABORT;
874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100876
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877 curproxy->next = proxy;
878 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200879 curproxy->conf.file = file;
880 curproxy->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200882 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200883 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200884 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100885 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200886 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200887 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888
Willy Tarreauee991362007-05-14 14:37:50 +0200889 /* Timeouts are defined as -1, so we cannot use the zeroed area
890 * as a default value.
891 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100892 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200893
894 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100896 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897
898 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100899 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200900 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200901 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200902 err_code |= ERR_FATAL;
903 goto out;
904 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200905 new = curproxy->listen;
906 while (new != last) {
907 new->conf.file = file;
908 new->conf.line = linenum;
909 new = new->next;
910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 global.maxsock++;
912 }
913
914 /* set default values */
915 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100917 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200918 curproxy->no_options = defproxy.no_options;
919 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100920 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100921 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200922 curproxy->except_net = defproxy.except_net;
923 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200924 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200925 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200927 if (defproxy.fwdfor_hdr_len) {
928 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
929 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
930 }
931
Willy Tarreau977b8e42006-12-29 14:19:17 +0100932 if (curproxy->cap & PR_CAP_FE) {
933 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100934 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200935 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100936
937 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200938 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
939 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100940
941 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943
Willy Tarreau977b8e42006-12-29 14:19:17 +0100944 if (curproxy->cap & PR_CAP_BE) {
945 curproxy->fullconn = defproxy.fullconn;
946 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947
Willy Tarreau977b8e42006-12-29 14:19:17 +0100948 if (defproxy.check_req)
949 curproxy->check_req = strdup(defproxy.check_req);
950 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951
Willy Tarreau977b8e42006-12-29 14:19:17 +0100952 if (defproxy.cookie_name)
953 curproxy->cookie_name = strdup(defproxy.cookie_name);
954 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100955
Emeric Brun647caf12009-06-30 17:57:00 +0200956 if (defproxy.rdp_cookie_name)
957 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
958 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
959
Willy Tarreau01732802007-11-01 22:48:15 +0100960 if (defproxy.url_param_name)
961 curproxy->url_param_name = strdup(defproxy.url_param_name);
962 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100963
Benoitaffb4812009-03-25 13:02:10 +0100964 if (defproxy.hh_name)
965 curproxy->hh_name = strdup(defproxy.hh_name);
966 curproxy->hh_len = defproxy.hh_len;
967 curproxy->hh_match_domain = defproxy.hh_match_domain;
968
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100969 if (defproxy.iface_name)
970 curproxy->iface_name = strdup(defproxy.iface_name);
971 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200974 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100975 if (defproxy.capture_name)
976 curproxy->capture_name = strdup(defproxy.capture_name);
977 curproxy->capture_namelen = defproxy.capture_namelen;
978 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980
Willy Tarreau977b8e42006-12-29 14:19:17 +0100981 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100982 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100983 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100984 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100985 curproxy->uri_auth = defproxy.uri_auth;
986 curproxy->mon_net = defproxy.mon_net;
987 curproxy->mon_mask = defproxy.mon_mask;
988 if (defproxy.monitor_uri)
989 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
990 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100991 if (defproxy.defbe.name)
992 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100993 }
994
995 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100996 curproxy->timeout.connect = defproxy.timeout.connect;
997 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100998 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100999 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001000 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001001 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001002 curproxy->source_addr = defproxy.source_addr;
1003 }
1004
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 curproxy->mode = defproxy.mode;
1006 curproxy->logfac1 = defproxy.logfac1;
1007 curproxy->logsrv1 = defproxy.logsrv1;
1008 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001009 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 curproxy->logfac2 = defproxy.logfac2;
1011 curproxy->logsrv2 = defproxy.logsrv2;
1012 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001013 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001015 curproxy->conf.used_listener_id = EB_ROOT;
1016 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001017
Willy Tarreau93893792009-07-23 13:19:11 +02001018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 }
1020 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1021 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001022 /* FIXME-20070101: we should do this too at the end of the
1023 * config parsing to free all default values.
1024 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001025 free(defproxy.check_req);
1026 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001027 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001028 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001029 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001030 free(defproxy.capture_name);
1031 free(defproxy.monitor_uri);
1032 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001033 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001034 free(defproxy.fwdfor_hdr_name);
1035 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001036
Willy Tarreaua534fea2008-08-03 12:19:50 +02001037 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001038 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001039
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 /* we cannot free uri_auth because it might already be used */
1041 init_default_instance();
1042 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001043 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 }
1046 else if (curproxy == NULL) {
1047 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 }
1051
Willy Tarreau977b8e42006-12-29 14:19:17 +01001052
1053 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001055 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001056 int cur_arg;
1057
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 if (curproxy == &defproxy) {
1059 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001064 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065
1066 if (strchr(args[1], ':') == NULL) {
1067 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1068 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001069 err_code |= ERR_ALERT | ERR_FATAL;
1070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001072
1073 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001074 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
1077 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001078
Willy Tarreau90a570f2009-10-04 20:54:54 +02001079 new_listen = curproxy->listen;
1080 while (new_listen != last_listen) {
1081 new_listen->conf.file = file;
1082 new_listen->conf.line = linenum;
1083 new_listen = new_listen->next;
1084 }
1085
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001086 cur_arg = 2;
1087 while (*(args[cur_arg])) {
1088 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1089#ifdef SO_BINDTODEVICE
1090 struct listener *l;
1091
1092 if (!*args[cur_arg + 1]) {
1093 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1094 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001097 }
1098
1099 for (l = curproxy->listen; l != last_listen; l = l->next)
1100 l->interface = strdup(args[cur_arg + 1]);
1101
1102 global.last_checks |= LSTCHK_NETADM;
1103
1104 cur_arg += 2;
1105 continue;
1106#else
1107 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1108 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001111#endif
1112 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001113 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1114#ifdef TCP_MAXSEG
1115 struct listener *l;
1116 int mss;
1117
1118 if (!*args[cur_arg + 1]) {
1119 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001123 }
1124
1125 mss = str2uic(args[cur_arg + 1]);
1126 if (mss < 1 || mss > 65535) {
1127 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1128 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001129 err_code |= ERR_ALERT | ERR_FATAL;
1130 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001131 }
1132
1133 for (l = curproxy->listen; l != last_listen; l = l->next)
1134 l->maxseg = mss;
1135
1136 cur_arg += 2;
1137 continue;
1138#else
1139 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1140 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001143#endif
1144 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001145 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001146#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001147 struct listener *l;
1148
1149 for (l = curproxy->listen; l != last_listen; l = l->next)
1150 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001151
1152 cur_arg ++;
1153 continue;
1154#else
1155 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1156 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001159#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001160 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001161
1162 if (!strcmp(args[cur_arg], "name")) {
1163 struct listener *l;
1164
1165 for (l = curproxy->listen; l != last_listen; l = l->next)
1166 l->name = strdup(args[cur_arg + 1]);
1167
1168 cur_arg += 2;
1169 continue;
1170 }
1171
1172 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001173 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001174 struct listener *l;
1175
1176 if (curproxy->listen->next != last_listen) {
1177 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1178 file, linenum, args[cur_arg]);
1179 err_code |= ERR_ALERT | ERR_FATAL;
1180 goto out;
1181 }
1182
1183 if (!*args[cur_arg + 1]) {
1184 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1185 file, linenum, args[cur_arg]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
1189
1190 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001191 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001192
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001193 if (curproxy->listen->luid <= 0) {
1194 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001195 file, linenum);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
1198 }
1199
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001200 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1201 if (node) {
1202 l = container_of(node, struct listener, conf.id);
1203 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1204 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1209
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001210 cur_arg += 2;
1211 continue;
1212 }
1213
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001214 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001221 }
1222 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1223 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1224 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1225 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001229 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001230 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001231
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 /* flush useless bits */
1233 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001235 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001236 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001237 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001238 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001239
Willy Tarreau1c47f852006-07-09 08:22:27 +02001240 if (!*args[1]) {
1241 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001245 }
1246
Willy Tarreaua534fea2008-08-03 12:19:50 +02001247 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001248 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001249 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001250 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001251 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1252
Willy Tarreau93893792009-07-23 13:19:11 +02001253 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1256 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1257 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1258 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1259 else {
1260 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 }
1264 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001265 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001266 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001267
1268 if (curproxy == &defproxy) {
1269 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1270 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001273 }
1274
1275 if (!*args[1]) {
1276 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1277 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001280 }
1281
1282 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001283 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001284
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001285 if (curproxy->uuid <= 0) {
1286 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001287 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001290 }
1291
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001292 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1293 if (node) {
1294 struct proxy *target = container_of(node, struct proxy, conf.id);
1295 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1296 file, linenum, proxy_type_str(curproxy), curproxy->id,
1297 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001302 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001303 else if (!strcmp(args[0], "description")) {
1304 int i, len=0;
1305 char *d;
1306
1307 if (!*args[1]) {
1308 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1309 file, linenum, args[0]);
1310 return -1;
1311 }
1312
1313 for(i=1; *args[i]; i++)
1314 len += strlen(args[i])+1;
1315
1316 d = (char *)calloc(1, len);
1317 curproxy->desc = d;
1318
1319 d += sprintf(d, "%s", args[1]);
1320 for(i=2; *args[i]; i++)
1321 d += sprintf(d, " %s", args[i]);
1322
1323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1325 curproxy->state = PR_STSTOPPED;
1326 }
1327 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1328 curproxy->state = PR_STNEW;
1329 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001330 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1331 int cur_arg = 1;
1332 unsigned int set = 0;
1333
1334 while (*args[cur_arg]) {
1335 int u;
1336 if (strcmp(args[cur_arg], "all") == 0) {
1337 set = 0;
1338 break;
1339 }
1340 else if (strcmp(args[cur_arg], "odd") == 0) {
1341 set |= 0x55555555;
1342 }
1343 else if (strcmp(args[cur_arg], "even") == 0) {
1344 set |= 0xAAAAAAAA;
1345 }
1346 else {
1347 u = str2uic(args[cur_arg]);
1348 if (u < 1 || u > 32) {
1349 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1350 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001353 }
1354 if (u > global.nbproc) {
1355 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1356 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001357 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001358 }
1359 set |= 1 << (u - 1);
1360 }
1361 cur_arg++;
1362 }
1363 curproxy->bind_proc = set;
1364 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001365 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001366 if (curproxy == &defproxy) {
1367 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001370 }
1371
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001372 err = invalid_char(args[1]);
1373 if (err) {
1374 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1375 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001376 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001377 }
1378
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001379 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1380 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1381 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
1383 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001384 }
1385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1387 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388
Willy Tarreau977b8e42006-12-29 14:19:17 +01001389 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001390 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001391
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 if (*(args[1]) == 0) {
1393 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1394 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001398
1399 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 curproxy->cookie_name = strdup(args[1]);
1401 curproxy->cookie_len = strlen(curproxy->cookie_name);
1402
1403 cur_arg = 2;
1404 while (*(args[cur_arg])) {
1405 if (!strcmp(args[cur_arg], "rewrite")) {
1406 curproxy->options |= PR_O_COOK_RW;
1407 }
1408 else if (!strcmp(args[cur_arg], "indirect")) {
1409 curproxy->options |= PR_O_COOK_IND;
1410 }
1411 else if (!strcmp(args[cur_arg], "insert")) {
1412 curproxy->options |= PR_O_COOK_INS;
1413 }
1414 else if (!strcmp(args[cur_arg], "nocache")) {
1415 curproxy->options |= PR_O_COOK_NOC;
1416 }
1417 else if (!strcmp(args[cur_arg], "postonly")) {
1418 curproxy->options |= PR_O_COOK_POST;
1419 }
1420 else if (!strcmp(args[cur_arg], "prefix")) {
1421 curproxy->options |= PR_O_COOK_PFX;
1422 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001423 else if (!strcmp(args[cur_arg], "domain")) {
1424 if (!*args[cur_arg + 1]) {
1425 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1426 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001427 err_code |= ERR_ALERT | ERR_FATAL;
1428 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001429 }
1430
1431 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1432 /* rfc2109, 4.3.2 Rejecting Cookies */
1433 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1434 " dots or does not start with a dot.\n",
1435 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001438 }
1439
1440 err = invalid_domainchar(args[cur_arg + 1]);
1441 if (err) {
1442 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1443 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001444 err_code |= ERR_ALERT | ERR_FATAL;
1445 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001446 }
1447
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001448 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001449 cur_arg++;
1450 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001452 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
1457 cur_arg++;
1458 }
1459 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1460 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1461 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 }
1464
1465 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1466 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001468 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 }
1470 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001471 else if (!strcmp(args[0], "persist")) { /* persist */
1472 if (*(args[1]) == 0) {
1473 Alert("parsing [%s:%d] : missing persist method.\n",
1474 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001477 }
1478
1479 if (!strncmp(args[1], "rdp-cookie", 10)) {
1480 curproxy->options2 |= PR_O2_RDPC_PRST;
1481
1482 if (*(args[1] + 10 ) == '(') { /* cookie name */
1483 const char *beg, *end;
1484
1485 beg = args[1] + 11;
1486 end = strchr(beg, ')');
1487
1488 if (!end || end == beg) {
1489 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1490 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001491 err_code |= ERR_ALERT | ERR_FATAL;
1492 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001493 }
1494
1495 free(curproxy->rdp_cookie_name);
1496 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1497 curproxy->rdp_cookie_len = end-beg;
1498 }
1499 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1500 free(curproxy->rdp_cookie_name);
1501 curproxy->rdp_cookie_name = strdup("msts");
1502 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1503 }
1504 else { /* syntax */
1505 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1506 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
1508 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001509 }
1510 }
1511 else {
1512 Alert("parsing [%s:%d] : unknown persist method.\n",
1513 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001514 err_code |= ERR_ALERT | ERR_FATAL;
1515 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001516 }
1517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001521 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 if (*(args[5]) == 0) {
1524 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1525 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001526 err_code |= ERR_ALERT | ERR_FATAL;
1527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 }
1529 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001530 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 curproxy->appsession_name = strdup(args[1]);
1532 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1533 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001534 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1535 if (err) {
1536 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1537 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001540 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001541 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001542
Willy Tarreau51041c72007-09-09 21:56:53 +02001543 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1544 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001545 err_code |= ERR_ALERT | ERR_ABORT;
1546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 }
1548 } /* Url App Session */
1549 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001550 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001551 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 if (*(args[4]) == 0) {
1555 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001557 err_code |= ERR_ALERT | ERR_FATAL;
1558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001560 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 curproxy->capture_name = strdup(args[2]);
1562 curproxy->capture_namelen = strlen(curproxy->capture_name);
1563 curproxy->capture_len = atol(args[4]);
1564 if (curproxy->capture_len >= CAPTURE_LEN) {
1565 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1566 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001567 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 curproxy->capture_len = CAPTURE_LEN - 1;
1569 }
1570 curproxy->to_log |= LW_COOKIE;
1571 }
1572 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1573 struct cap_hdr *hdr;
1574
1575 if (curproxy == &defproxy) {
1576 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 +02001577 err_code |= ERR_ALERT | ERR_FATAL;
1578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 }
1580
1581 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1582 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1583 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
1587
1588 hdr = calloc(sizeof(struct cap_hdr), 1);
1589 hdr->next = curproxy->req_cap;
1590 hdr->name = strdup(args[3]);
1591 hdr->namelen = strlen(args[3]);
1592 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001593 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 hdr->index = curproxy->nb_req_cap++;
1595 curproxy->req_cap = hdr;
1596 curproxy->to_log |= LW_REQHDR;
1597 }
1598 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1599 struct cap_hdr *hdr;
1600
1601 if (curproxy == &defproxy) {
1602 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 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
1604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
1606
1607 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1608 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1609 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612 }
1613 hdr = calloc(sizeof(struct cap_hdr), 1);
1614 hdr->next = curproxy->rsp_cap;
1615 hdr->name = strdup(args[3]);
1616 hdr->namelen = strlen(args[3]);
1617 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001618 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 hdr->index = curproxy->nb_rsp_cap++;
1620 curproxy->rsp_cap = hdr;
1621 curproxy->to_log |= LW_RSPHDR;
1622 }
1623 else {
1624 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1625 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 }
1629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001633
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 if (*(args[1]) == 0) {
1635 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
1640 curproxy->conn_retries = atol(args[1]);
1641 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001642 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1643 int pol = ACL_COND_NONE;
1644 struct acl_cond *cond;
1645
Willy Tarreaub099aca2008-10-12 17:26:37 +02001646 if (curproxy == &defproxy) {
1647 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001650 }
1651
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001652 if (!strcmp(args[1], "if"))
1653 pol = ACL_COND_IF;
1654 else if (!strcmp(args[1], "unless"))
1655 pol = ACL_COND_UNLESS;
1656
1657 if (pol == ACL_COND_NONE) {
1658 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001662 }
1663
1664 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1665 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1666 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001669 }
Willy Tarreau88922352009-10-04 22:02:50 +02001670 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001671 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001672 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001673 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001674 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001675 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001676 else if (!strcmp(args[0], "redirect")) {
1677 int pol = ACL_COND_NONE;
1678 struct acl_cond *cond;
1679 struct redirect_rule *rule;
1680 int cur_arg;
1681 int type = REDIRECT_TYPE_NONE;
1682 int code = 302;
1683 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001684 char *cookie = NULL;
1685 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001686 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001687
1688 cur_arg = 1;
1689 while (*(args[cur_arg])) {
1690 if (!strcmp(args[cur_arg], "location")) {
1691 if (!*args[cur_arg + 1]) {
1692 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1693 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001696 }
1697
1698 type = REDIRECT_TYPE_LOCATION;
1699 cur_arg++;
1700 destination = args[cur_arg];
1701 }
1702 else if (!strcmp(args[cur_arg], "prefix")) {
1703 if (!*args[cur_arg + 1]) {
1704 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1705 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001706 err_code |= ERR_ALERT | ERR_FATAL;
1707 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001708 }
1709
1710 type = REDIRECT_TYPE_PREFIX;
1711 cur_arg++;
1712 destination = args[cur_arg];
1713 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001714 else if (!strcmp(args[cur_arg], "set-cookie")) {
1715 if (!*args[cur_arg + 1]) {
1716 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1717 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001720 }
1721
1722 cur_arg++;
1723 cookie = args[cur_arg];
1724 cookie_set = 1;
1725 }
1726 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1727 if (!*args[cur_arg + 1]) {
1728 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1729 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001732 }
1733
1734 cur_arg++;
1735 cookie = args[cur_arg];
1736 cookie_set = 0;
1737 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001738 else if (!strcmp(args[cur_arg],"code")) {
1739 if (!*args[cur_arg + 1]) {
1740 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1741 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001744 }
1745 cur_arg++;
1746 code = atol(args[cur_arg]);
1747 if (code < 301 || code > 303) {
1748 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1749 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001752 }
1753 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001754 else if (!strcmp(args[cur_arg],"drop-query")) {
1755 flags |= REDIRECT_FLAG_DROP_QS;
1756 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001757 else if (!strcmp(args[cur_arg], "if")) {
1758 pol = ACL_COND_IF;
1759 cur_arg++;
1760 break;
1761 }
1762 else if (!strcmp(args[cur_arg], "unless")) {
1763 pol = ACL_COND_UNLESS;
1764 cur_arg++;
1765 break;
1766 }
1767 else {
1768 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1769 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001772 }
1773 cur_arg++;
1774 }
1775
1776 if (type == REDIRECT_TYPE_NONE) {
1777 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001781 }
1782
1783 if (pol == ACL_COND_NONE) {
1784 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1785 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001788 }
1789
1790 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001791 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001792 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001795 }
1796
Willy Tarreau88922352009-10-04 22:02:50 +02001797 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001798 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001799 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001800 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1801 rule->cond = cond;
1802 rule->rdr_str = strdup(destination);
1803 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001804 if (cookie) {
1805 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1806 * a clear consists in appending "; Max-Age=0" at the end.
1807 */
1808 rule->cookie_len = strlen(cookie);
1809 if (cookie_set)
1810 rule->cookie_str = strdup(cookie);
1811 else {
1812 rule->cookie_str = malloc(rule->cookie_len + 12);
1813 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1814 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1815 rule->cookie_len += 11;
1816 }
1817 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001818 rule->type = type;
1819 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001820 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001821 LIST_INIT(&rule->list);
1822 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001823 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001824 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001825 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001826 int pol = ACL_COND_NONE;
1827 struct acl_cond *cond;
1828 struct switching_rule *rule;
1829
Willy Tarreaub099aca2008-10-12 17:26:37 +02001830 if (curproxy == &defproxy) {
1831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001834 }
1835
Willy Tarreau55ea7572007-06-17 19:56:27 +02001836 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001837 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001838
1839 if (*(args[1]) == 0) {
1840 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001841 err_code |= ERR_ALERT | ERR_FATAL;
1842 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001843 }
1844
1845 if (!strcmp(args[2], "if"))
1846 pol = ACL_COND_IF;
1847 else if (!strcmp(args[2], "unless"))
1848 pol = ACL_COND_UNLESS;
1849
1850 if (pol == ACL_COND_NONE) {
1851 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1852 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001855 }
1856
1857 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001858 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001859 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001862 }
1863
Willy Tarreau88922352009-10-04 22:02:50 +02001864 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001865 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001866 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001867 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001868 struct acl *acl;
1869 const char *name;
1870
1871 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1872 name = acl ? acl->name : "(unknown)";
1873 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1874 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001876 }
1877
Willy Tarreau55ea7572007-06-17 19:56:27 +02001878 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1879 rule->cond = cond;
1880 rule->be.name = strdup(args[1]);
1881 LIST_INIT(&rule->list);
1882 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001885 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001886 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001887
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1889 curproxy->uri_auth = NULL; /* we must detach from the default config */
1890
1891 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001892 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable', 'hide-version', 'show-node', 'show-desc'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 } else if (!strcmp(args[1], "uri")) {
1896 if (*(args[2]) == 0) {
1897 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1901 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001902 err_code |= ERR_ALERT | ERR_ABORT;
1903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 }
1905 } else if (!strcmp(args[1], "realm")) {
1906 if (*(args[2]) == 0) {
1907 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1911 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001912 err_code |= ERR_ALERT | ERR_ABORT;
1913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001915 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001916 unsigned interval;
1917
1918 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1919 if (err) {
1920 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1921 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001924 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1925 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_ALERT | ERR_ABORT;
1927 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 } else if (!strcmp(args[1], "auth")) {
1930 if (*(args[2]) == 0) {
1931 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1935 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_ALERT | ERR_ABORT;
1937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 }
1939 } else if (!strcmp(args[1], "scope")) {
1940 if (*(args[2]) == 0) {
1941 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1945 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_ABORT;
1947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948 }
1949 } else if (!strcmp(args[1], "enable")) {
1950 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1951 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_ALERT | ERR_ABORT;
1953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001955 } else if (!strcmp(args[1], "hide-version")) {
1956 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1957 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_ABORT;
1959 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001960 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001961 } else if (!strcmp(args[1], "show-node")) {
1962
1963 if (*args[2]) {
1964 int i;
1965 char c;
1966
1967 for (i=0; args[2][i]; i++) {
1968 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02001969 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001970 break;
1971 }
1972
1973 if (!i || args[2][i]) {
1974 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1975 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1976 file, linenum, args[0], args[1]);
1977 err_code |= ERR_ALERT | ERR_FATAL;
1978 goto out;
1979 }
1980 }
1981
1982 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1983 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1984 err_code |= ERR_ALERT | ERR_ABORT;
1985 goto out;
1986 }
1987 } else if (!strcmp(args[1], "show-desc")) {
1988 char *desc = NULL;
1989
1990 if (*args[2]) {
1991 int i, len=0;
1992 char *d;
1993
1994 for(i=2; *args[i]; i++)
1995 len += strlen(args[i])+1;
1996
1997 desc = d = (char *)calloc(1, len);
1998
1999 d += sprintf(d, "%s", args[2]);
2000 for(i=3; *args[i]; i++)
2001 d += sprintf(d, " %s", args[i]);
2002 }
2003
2004 if (!*args[2] && !global.desc)
2005 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2006 file, linenum, args[1]);
2007 else {
2008 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2009 free(desc);
2010 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2011 err_code |= ERR_ALERT | ERR_ABORT;
2012 goto out;
2013 }
2014 free(desc);
2015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002016 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002017 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 }
2022 }
2023 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002024 int optnum;
2025
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002026 if (*(args[1]) == '\0') {
2027 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2028 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002032
2033 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2034 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002035 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2036 err_code |= ERR_WARN;
2037 goto out;
2038 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002039
Willy Tarreau3842f002009-06-14 11:39:52 +02002040 curproxy->no_options &= ~cfg_opts[optnum].val;
2041 curproxy->options &= ~cfg_opts[optnum].val;
2042
2043 switch (kwm) {
2044 case KWM_STD:
2045 curproxy->options |= cfg_opts[optnum].val;
2046 break;
2047 case KWM_NO:
2048 curproxy->no_options |= cfg_opts[optnum].val;
2049 break;
2050 case KWM_DEF: /* already cleared */
2051 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002052 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002053
Willy Tarreau93893792009-07-23 13:19:11 +02002054 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002055 }
2056 }
2057
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002058 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2059 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002060 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2061 err_code |= ERR_WARN;
2062 goto out;
2063 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002064
Willy Tarreau3842f002009-06-14 11:39:52 +02002065 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2066 curproxy->options2 &= ~cfg_opts2[optnum].val;
2067
2068 switch (kwm) {
2069 case KWM_STD:
2070 curproxy->options2 |= cfg_opts2[optnum].val;
2071 break;
2072 case KWM_NO:
2073 curproxy->no_options2 |= cfg_opts2[optnum].val;
2074 break;
2075 case KWM_DEF: /* already cleared */
2076 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002077 }
Willy Tarreau93893792009-07-23 13:19:11 +02002078 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002079 }
2080 }
2081
Willy Tarreau3842f002009-06-14 11:39:52 +02002082 if (kwm != KWM_STD) {
2083 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002084 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002087 }
2088
Emeric Brun3a058f32009-06-30 18:26:00 +02002089 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002091 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002093 if (*(args[2]) != '\0') {
2094 if (!strcmp(args[2], "clf")) {
2095 curproxy->options2 |= PR_O2_CLFLOG;
2096 } else {
2097 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002100 }
2101 }
2102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 else if (!strcmp(args[1], "tcplog"))
2104 /* generate a detailed TCP log */
2105 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 else if (!strcmp(args[1], "tcpka")) {
2107 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002108 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002109 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002110
2111 if (curproxy->cap & PR_CAP_FE)
2112 curproxy->options |= PR_O_TCP_CLI_KA;
2113 if (curproxy->cap & PR_CAP_BE)
2114 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 }
2116 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002117 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002118 err_code |= ERR_WARN;
2119
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002121 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002122 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002123 curproxy->options &= ~PR_O_SMTP_CHK;
2124 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 if (!*args[2]) { /* no argument */
2126 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2127 curproxy->check_len = strlen(DEF_CHECK_REQ);
2128 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002129 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002130 curproxy->check_req = (char *)malloc(reqlen);
2131 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2132 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2133 } else { /* more arguments : METHOD URI [HTTP_VER] */
2134 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2135 if (*args[4])
2136 reqlen += strlen(args[4]);
2137 else
2138 reqlen += strlen("HTTP/1.0");
2139
2140 curproxy->check_req = (char *)malloc(reqlen);
2141 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2142 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2143 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002144 }
2145 else if (!strcmp(args[1], "ssl-hello-chk")) {
2146 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002147 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002149
Willy Tarreaua534fea2008-08-03 12:19:50 +02002150 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002151 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002152 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002153 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 }
Willy Tarreau23677902007-05-08 23:50:35 +02002155 else if (!strcmp(args[1], "smtpchk")) {
2156 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002157 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002158 curproxy->options &= ~PR_O_HTTP_CHK;
2159 curproxy->options &= ~PR_O_SSL3_CHK;
2160 curproxy->options |= PR_O_SMTP_CHK;
2161
2162 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2163 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2164 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2165 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2166 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2167 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2168 curproxy->check_req = (char *)malloc(reqlen);
2169 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2170 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2171 } else {
2172 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2173 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2174 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2175 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2176 }
2177 }
2178 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002179 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002180 int cur_arg;
2181
2182 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2183 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002184 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002185
2186 curproxy->options |= PR_O_FWDFOR;
2187
2188 free(curproxy->fwdfor_hdr_name);
2189 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2190 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2191
2192 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2193 cur_arg = 2;
2194 while (*(args[cur_arg])) {
2195 if (!strcmp(args[cur_arg], "except")) {
2196 /* suboption except - needs additional argument for it */
2197 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2198 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2199 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002202 }
2203 /* flush useless bits */
2204 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002205 cur_arg += 2;
2206 } else if (!strcmp(args[cur_arg], "header")) {
2207 /* suboption header - needs additional argument for it */
2208 if (*(args[cur_arg+1]) == 0) {
2209 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2210 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002213 }
2214 free(curproxy->fwdfor_hdr_name);
2215 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2216 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2217 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002218 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002219 /* unknown suboption - catchall */
2220 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2221 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002224 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002225 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002226 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002227 else if (!strcmp(args[1], "originalto")) {
2228 int cur_arg;
2229
2230 /* insert x-original-to field, but not for the IP address listed as an except.
2231 * set default options (ie: bitfield, header name, etc)
2232 */
2233
2234 curproxy->options |= PR_O_ORGTO;
2235
2236 free(curproxy->orgto_hdr_name);
2237 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2238 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2239
2240 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2241 cur_arg = 2;
2242 while (*(args[cur_arg])) {
2243 if (!strcmp(args[cur_arg], "except")) {
2244 /* suboption except - needs additional argument for it */
2245 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2246 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2247 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002250 }
2251 /* flush useless bits */
2252 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2253 cur_arg += 2;
2254 } else if (!strcmp(args[cur_arg], "header")) {
2255 /* suboption header - needs additional argument for it */
2256 if (*(args[cur_arg+1]) == 0) {
2257 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2258 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002261 }
2262 free(curproxy->orgto_hdr_name);
2263 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2264 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2265 cur_arg += 2;
2266 } else {
2267 /* unknown suboption - catchall */
2268 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2269 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002272 }
2273 } /* end while loop */
2274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 else {
2276 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
Willy Tarreau93893792009-07-23 13:19:11 +02002280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002282 else if (!strcmp(args[0], "default_backend")) {
2283 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002285
2286 if (*(args[1]) == 0) {
2287 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002290 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002291 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002292 curproxy->defbe.name = strdup(args[1]);
2293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002298 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 /* enable reconnections to dispatch */
2302 curproxy->options |= PR_O_REDISP;
2303 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002304 else if (!strcmp(args[0], "http-check")) {
2305 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002306 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002307
2308 if (strcmp(args[1], "disable-on-404") == 0) {
2309 /* enable a graceful server shutdown on an HTTP 404 response */
2310 curproxy->options |= PR_O_DISABLE404;
2311 }
2312 else {
2313 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002316 }
2317 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002318 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002319 if (curproxy == &defproxy) {
2320 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002323 }
2324
Willy Tarreaub80c2302007-11-30 20:51:32 +01002325 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002327
2328 if (strcmp(args[1], "fail") == 0) {
2329 /* add a condition to fail monitor requests */
2330 int pol = ACL_COND_NONE;
2331 struct acl_cond *cond;
2332
2333 if (!strcmp(args[2], "if"))
2334 pol = ACL_COND_IF;
2335 else if (!strcmp(args[2], "unless"))
2336 pol = ACL_COND_UNLESS;
2337
2338 if (pol == ACL_COND_NONE) {
2339 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2340 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002343 }
2344
2345 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2346 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2347 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002350 }
Willy Tarreau88922352009-10-04 22:02:50 +02002351 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002352 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002353 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002354 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2355 }
2356 else {
2357 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002360 }
2361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362#ifdef TPROXY
2363 else if (!strcmp(args[0], "transparent")) {
2364 /* enable transparent proxy connections */
2365 curproxy->options |= PR_O_TRANSP;
2366 }
2367#endif
2368 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 if (*(args[1]) == 0) {
2373 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }
2377 curproxy->maxconn = atol(args[1]);
2378 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002379 else if (!strcmp(args[0], "backlog")) { /* backlog */
2380 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002382
2383 if (*(args[1]) == 0) {
2384 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002387 }
2388 curproxy->backlog = atol(args[1]);
2389 }
Willy Tarreau86034312006-12-29 00:10:33 +01002390 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002392 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002393
Willy Tarreau86034312006-12-29 00:10:33 +01002394 if (*(args[1]) == 0) {
2395 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002398 }
2399 curproxy->fullconn = atol(args[1]);
2400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2402 if (*(args[1]) == 0) {
2403 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002407 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2408 if (err) {
2409 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2410 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002413 }
2414 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 }
2416 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2417 if (curproxy == &defproxy) {
2418 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 if (strchr(args[1], ':') == NULL) {
2426 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
2430 curproxy->dispatch_addr = *str2sa(args[1]);
2431 }
2432 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002435
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002436 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002437 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2438 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 else if (!strcmp(args[0], "server")) { /* server address */
2444 int cur_arg;
2445 char *rport;
2446 char *raddr;
2447 short realport;
2448 int do_check;
2449
2450 if (curproxy == &defproxy) {
2451 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002455 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457
2458 if (!*args[2]) {
2459 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002464
2465 err = invalid_char(args[1]);
2466 if (err) {
2467 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2468 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002471 }
2472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
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
2479 /* the servers are linked backwards first */
2480 newsrv->next = curproxy->srv;
2481 curproxy->srv = newsrv;
2482 newsrv->proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002483 newsrv->conf.file = file;
2484 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485
2486 LIST_INIT(&newsrv->pendconns);
2487 do_check = 0;
2488 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002489 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 newsrv->id = strdup(args[1]);
2491
2492 /* several ways to check the port component :
2493 * - IP => port=+0, relative
2494 * - IP: => port=+0, relative
2495 * - IP:N => port=N, absolute
2496 * - IP:+N => port=+N, relative
2497 * - IP:-N => port=-N, relative
2498 */
2499 raddr = strdup(args[2]);
2500 rport = strchr(raddr, ':');
2501 if (rport) {
2502 *rport++ = 0;
2503 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002504 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 newsrv->state |= SRV_MAPPORTS;
2506 } else {
2507 realport = 0;
2508 newsrv->state |= SRV_MAPPORTS;
2509 }
2510
2511 newsrv->addr = *str2sa(raddr);
2512 newsrv->addr.sin_port = htons(realport);
2513 free(raddr);
2514
2515 newsrv->curfd = -1; /* no health-check in progress */
2516 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002517 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2518 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 newsrv->rise = DEF_RISETIME;
2520 newsrv->fall = DEF_FALLTIME;
2521 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002522 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002523 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002524 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002525
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 cur_arg = 3;
2527 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002528 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002529 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002530
2531 if (!*args[cur_arg + 1]) {
2532 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2533 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002536 }
2537
2538 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002539 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002540
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002541 if (newsrv->puid <= 0) {
2542 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002543 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002546 }
2547
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002548 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2549 if (node) {
2550 struct server *target = container_of(node, struct server, conf.id);
2551 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2552 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
2555 }
2556 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002557 cur_arg += 2;
2558 }
2559 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 newsrv->cookie = strdup(args[cur_arg + 1]);
2561 newsrv->cklen = strlen(args[cur_arg + 1]);
2562 cur_arg += 2;
2563 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002564 else if (!strcmp(args[cur_arg], "redir")) {
2565 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2566 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2567 cur_arg += 2;
2568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002570 if (!*args[cur_arg + 1]) {
2571 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2572 file, linenum, args[cur_arg]);
2573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
2575 }
2576
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002578 if (newsrv->rise <= 0) {
2579 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2580 file, linenum, args[cur_arg]);
2581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
2583 }
2584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 newsrv->health = newsrv->rise;
2586 cur_arg += 2;
2587 }
2588 else if (!strcmp(args[cur_arg], "fall")) {
2589 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002590
2591 if (!*args[cur_arg + 1]) {
2592 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2593 file, linenum, args[cur_arg]);
2594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
2596 }
2597
2598 if (newsrv->fall <= 0) {
2599 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2600 file, linenum, args[cur_arg]);
2601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
2603 }
2604
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 cur_arg += 2;
2606 }
2607 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002608 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2609 if (err) {
2610 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2611 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002614 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002615 if (val <= 0) {
2616 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2617 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002620 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002621 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 cur_arg += 2;
2623 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002624 else if (!strcmp(args[cur_arg], "fastinter")) {
2625 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2626 if (err) {
2627 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2628 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002631 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002632 if (val <= 0) {
2633 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2634 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002637 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002638 newsrv->fastinter = val;
2639 cur_arg += 2;
2640 }
2641 else if (!strcmp(args[cur_arg], "downinter")) {
2642 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2643 if (err) {
2644 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2645 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002648 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002649 if (val <= 0) {
2650 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2651 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002654 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002655 newsrv->downinter = val;
2656 cur_arg += 2;
2657 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002658 else if (!strcmp(args[cur_arg], "addr")) {
2659 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002660 cur_arg += 2;
2661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 else if (!strcmp(args[cur_arg], "port")) {
2663 newsrv->check_port = atol(args[cur_arg + 1]);
2664 cur_arg += 2;
2665 }
2666 else if (!strcmp(args[cur_arg], "backup")) {
2667 newsrv->state |= SRV_BACKUP;
2668 cur_arg ++;
2669 }
2670 else if (!strcmp(args[cur_arg], "weight")) {
2671 int w;
2672 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002673 if (w < 0 || w > 256) {
2674 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002679 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 cur_arg += 2;
2681 }
2682 else if (!strcmp(args[cur_arg], "minconn")) {
2683 newsrv->minconn = atol(args[cur_arg + 1]);
2684 cur_arg += 2;
2685 }
2686 else if (!strcmp(args[cur_arg], "maxconn")) {
2687 newsrv->maxconn = atol(args[cur_arg + 1]);
2688 cur_arg += 2;
2689 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002690 else if (!strcmp(args[cur_arg], "maxqueue")) {
2691 newsrv->maxqueue = atol(args[cur_arg + 1]);
2692 cur_arg += 2;
2693 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002694 else if (!strcmp(args[cur_arg], "slowstart")) {
2695 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002696 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002697 if (err) {
2698 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2699 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002702 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002703 if (val <= 0) {
2704 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2705 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002708 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002709 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002710 cur_arg += 2;
2711 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002712 else if (!strcmp(args[cur_arg], "track")) {
2713
2714 if (!*args[cur_arg + 1]) {
2715 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2716 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002719 }
2720
2721 newsrv->trackit = strdup(args[cur_arg + 1]);
2722
2723 cur_arg += 2;
2724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 else if (!strcmp(args[cur_arg], "check")) {
2726 global.maxsock++;
2727 do_check = 1;
2728 cur_arg += 1;
2729 }
2730 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002731 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002733#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002734 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002735 file, linenum, "source", "usesrc");
2736#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002737 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002739#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 }
2743 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002744 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2745
2746 if (port_low != port_high) {
2747 int i;
2748 if (port_low <= 0 || port_low > 65535 ||
2749 port_high <= 0 || port_high > 65535 ||
2750 port_low > port_high) {
2751 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2752 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002755 }
2756 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2757 for (i = 0; i < newsrv->sport_range->size; i++)
2758 newsrv->sport_range->ports[i] = port_low + i;
2759 }
2760
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002762 while (*(args[cur_arg])) {
2763 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002764#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2765#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002766 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2767 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2768 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002771 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002772#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002773 if (!*args[cur_arg + 1]) {
2774 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2775 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002778 }
2779 if (!strcmp(args[cur_arg + 1], "client")) {
2780 newsrv->state |= SRV_TPROXY_CLI;
2781 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2782 newsrv->state |= SRV_TPROXY_CIP;
2783 } else {
2784 newsrv->state |= SRV_TPROXY_ADDR;
2785 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2786 }
2787 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002788#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002789 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002790#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002791 cur_arg += 2;
2792 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002793#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002794 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002795 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002798#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2799 } /* "usesrc" */
2800
2801 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2802#ifdef SO_BINDTODEVICE
2803 if (!*args[cur_arg + 1]) {
2804 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2805 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002808 }
2809 if (newsrv->iface_name)
2810 free(newsrv->iface_name);
2811
2812 newsrv->iface_name = strdup(args[cur_arg + 1]);
2813 newsrv->iface_len = strlen(newsrv->iface_name);
2814 global.last_checks |= LSTCHK_NETADM;
2815#else
2816 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2817 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002820#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002821 cur_arg += 2;
2822 continue;
2823 }
2824 /* this keyword in not an option of "source" */
2825 break;
2826 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002828 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2829 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2830 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002835 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 }
2840 }
2841
2842 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002843 if (newsrv->trackit) {
2844 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2845 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002848 }
2849
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002850 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2851 newsrv->check_port = newsrv->check_addr.sin_port;
2852
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2854 newsrv->check_port = realport; /* by default */
2855 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002856 /* not yet valid, because no port was set on
2857 * the server either. We'll check if we have
2858 * a known port on the first listener.
2859 */
2860 struct listener *l;
2861 l = curproxy->listen;
2862 if (l) {
2863 int port;
2864 port = (l->addr.ss_family == AF_INET6)
2865 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2866 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2867 newsrv->check_port = port;
2868 }
2869 }
2870 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2872 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02002876
2877 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 newsrv->state |= SRV_CHECKED;
2879 }
2880
2881 if (newsrv->state & SRV_BACKUP)
2882 curproxy->srv_bck++;
2883 else
2884 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002885
2886 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
2888 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002889 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 int facility;
2891
2892 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2893 curproxy->logfac1 = global.logfac1;
2894 curproxy->logsrv1 = global.logsrv1;
2895 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002896 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 curproxy->logfac2 = global.logfac2;
2898 curproxy->logsrv2 = global.logsrv2;
2899 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002900 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 }
2902 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002903 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904
2905 facility = get_log_facility(args[2]);
2906 if (facility < 0) {
2907 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2908 exit(1);
2909 }
2910
2911 level = 7; /* max syslog level = debug */
2912 if (*(args[3])) {
2913 level = get_log_level(args[3]);
2914 if (level < 0) {
2915 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2916 exit(1);
2917 }
2918 }
2919
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002920 minlvl = 0; /* limit syslog level to this level (emerg) */
2921 if (*(args[4])) {
2922 minlvl = get_log_level(args[4]);
2923 if (level < 0) {
2924 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2925 exit(1);
2926 }
2927 }
2928
Robert Tsai81ae1952007-12-05 10:47:29 +01002929 if (args[1][0] == '/') {
2930 logsrv.u.addr.sa_family = AF_UNIX;
2931 logsrv.u.un = *str2sun(args[1]);
2932 } else {
2933 logsrv.u.addr.sa_family = AF_INET;
2934 logsrv.u.in = *str2sa(args[1]);
2935 if (!logsrv.u.in.sin_port) {
2936 logsrv.u.in.sin_port =
2937 htons(SYSLOG_PORT);
2938 }
2939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940
2941 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002942 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 curproxy->logfac1 = facility;
2944 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002945 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 }
2947 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002948 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 curproxy->logfac2 = facility;
2950 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002951 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 }
2953 else {
2954 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957 }
2958 }
2959 else {
2960 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2961 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 }
2965 }
2966 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002967 int cur_arg;
2968
Willy Tarreau977b8e42006-12-29 14:19:17 +01002969 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002971
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002973 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2974 file, linenum, "source", "usesrc", "interface");
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 Tarreau368480c2009-03-01 08:27:21 +01002978
2979 /* we must first clear any optional default setting */
2980 curproxy->options &= ~PR_O_TPXY_MASK;
2981 free(curproxy->iface_name);
2982 curproxy->iface_name = NULL;
2983 curproxy->iface_len = 0;
2984
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 curproxy->source_addr = *str2sa(args[1]);
2986 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002987
2988 cur_arg = 2;
2989 while (*(args[cur_arg])) {
2990 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002991#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2992#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002993 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2994 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2995 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002998 }
2999#endif
3000 if (!*args[cur_arg + 1]) {
3001 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3002 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003005 }
3006
3007 if (!strcmp(args[cur_arg + 1], "client")) {
3008 curproxy->options |= PR_O_TPXY_CLI;
3009 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3010 curproxy->options |= PR_O_TPXY_CIP;
3011 } else {
3012 curproxy->options |= PR_O_TPXY_ADDR;
3013 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3014 }
3015 global.last_checks |= LSTCHK_NETADM;
3016#if !defined(CONFIG_HAP_LINUX_TPROXY)
3017 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003018#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003019#else /* no TPROXY support */
3020 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003021 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003024#endif
3025 cur_arg += 2;
3026 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003027 }
3028
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003029 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3030#ifdef SO_BINDTODEVICE
3031 if (!*args[cur_arg + 1]) {
3032 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003036 }
3037 if (curproxy->iface_name)
3038 free(curproxy->iface_name);
3039
3040 curproxy->iface_name = strdup(args[cur_arg + 1]);
3041 curproxy->iface_len = strlen(curproxy->iface_name);
3042 global.last_checks |= LSTCHK_NETADM;
3043#else
3044 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3045 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003048#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003049 cur_arg += 2;
3050 continue;
3051 }
3052 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3053 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003058 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3059 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3060 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3065 regex_t *preg;
3066 if (curproxy == &defproxy) {
3067 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003071 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 if (*(args[1]) == 0 || *(args[2]) == 0) {
3075 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3076 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
3080
3081 preg = calloc(1, sizeof(regex_t));
3082 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3083 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
3087
3088 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3089 if (err) {
3090 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3091 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003094 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 }
3096 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3097 regex_t *preg;
3098 if (curproxy == &defproxy) {
3099 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003103 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003104 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003105
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 if (*(args[1]) == 0) {
3107 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 }
3111
3112 preg = calloc(1, sizeof(regex_t));
3113 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3114 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
3118
3119 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003120 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 }
3122 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3123 regex_t *preg;
3124 if (curproxy == &defproxy) {
3125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003129 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003131
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 if (*(args[1]) == 0) {
3133 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 }
3137
3138 preg = calloc(1, sizeof(regex_t));
3139 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3140 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 }
3144
3145 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003146 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3149 regex_t *preg;
3150 if (curproxy == &defproxy) {
3151 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003155 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003157
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 if (*(args[1]) == 0) {
3159 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 }
3163
3164 preg = calloc(1, sizeof(regex_t));
3165 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3166 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 }
3170
3171 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003172 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3175 regex_t *preg;
3176 if (curproxy == &defproxy) {
3177 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003181 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003183
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 if (*(args[1]) == 0) {
3185 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
3189
3190 preg = calloc(1, sizeof(regex_t));
3191 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3192 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196
3197 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003198 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003200 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3201 regex_t *preg;
3202 if (curproxy == &defproxy) {
3203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003206 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003207 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003209
Willy Tarreaub8750a82006-09-03 09:56:00 +02003210 if (*(args[1]) == 0) {
3211 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003214 }
3215
3216 preg = calloc(1, sizeof(regex_t));
3217 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3218 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003221 }
3222
3223 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003224 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003225 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003226 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3227 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003228 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003229 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003232 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003233 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003235
Willy Tarreau977b8e42006-12-29 14:19:17 +01003236 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003237 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3238 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003241 }
3242
3243 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003244 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003245 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003248 }
3249
3250 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003251 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003252 }
3253 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3254 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003255 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003256 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003259 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003260 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003262
Willy Tarreau977b8e42006-12-29 14:19:17 +01003263 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003264 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3265 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003268 }
3269
3270 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003271 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003272 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003275 }
3276
3277 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003278 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3281 regex_t *preg;
3282 if (curproxy == &defproxy) {
3283 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003287 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003289
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 if (*(args[1]) == 0 || *(args[2]) == 0) {
3291 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
3296
3297 preg = calloc(1, sizeof(regex_t));
3298 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3299 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
3303
3304 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3305 if (err) {
3306 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3307 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003311 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
3313 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3314 regex_t *preg;
3315 if (curproxy == &defproxy) {
3316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003320 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003322
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 if (*(args[1]) == 0) {
3324 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328
3329 preg = calloc(1, sizeof(regex_t));
3330 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3331 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
3335
3336 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003337 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
3339 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3340 regex_t *preg;
3341 if (curproxy == &defproxy) {
3342 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003346 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003348
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 if (*(args[1]) == 0) {
3350 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
3354
3355 preg = calloc(1, sizeof(regex_t));
3356 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3357 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
3361
3362 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003363 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 }
3365 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3366 regex_t *preg;
3367 if (curproxy == &defproxy) {
3368 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003372 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003373 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003374
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 if (*(args[1]) == 0) {
3376 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 }
3380
3381 preg = calloc(1, sizeof(regex_t));
3382 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3383 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
3387
3388 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003389 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 }
3391 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3392 regex_t *preg;
3393 if (curproxy == &defproxy) {
3394 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003398 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003400
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 if (*(args[1]) == 0) {
3402 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406
3407 preg = calloc(1, sizeof(regex_t));
3408 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3409 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
3413
3414 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003415 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003417 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3418 regex_t *preg;
3419 if (curproxy == &defproxy) {
3420 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003423 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003424 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003426
Willy Tarreaub8750a82006-09-03 09:56:00 +02003427 if (*(args[1]) == 0) {
3428 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003431 }
3432
3433 preg = calloc(1, sizeof(regex_t));
3434 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3435 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003438 }
3439
3440 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003441 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003443 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3444 if (curproxy == &defproxy) {
3445 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003449 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451
3452 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3453 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003456 }
3457
3458 if (*(args[1]) == 0) {
3459 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 }
3463
3464 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003465 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 }
3467 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3468 regex_t *preg;
3469
3470 if (*(args[1]) == 0 || *(args[2]) == 0) {
3471 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003476 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003478
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 preg = calloc(1, sizeof(regex_t));
3480 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3481 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 }
3485
3486 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3487 if (err) {
3488 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3489 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003493 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 }
3495 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3496 regex_t *preg;
3497 if (curproxy == &defproxy) {
3498 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003501 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003502 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003504
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 if (*(args[1]) == 0) {
3506 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 }
3510
3511 preg = calloc(1, sizeof(regex_t));
3512 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3513 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003514 err_code |= ERR_ALERT | ERR_FATAL;
3515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 }
3517
3518 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3519 if (err) {
3520 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3521 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
3525 }
3526 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3527 regex_t *preg;
3528 if (curproxy == &defproxy) {
3529 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003533 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003535
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 if (*(args[1]) == 0) {
3537 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 }
3541
3542 preg = calloc(1, sizeof(regex_t));
3543 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3544 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 }
3548
3549 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3550 if (err) {
3551 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3552 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
3556 }
3557 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3558 regex_t *preg;
3559 if (curproxy == &defproxy) {
3560 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003564 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566
3567 if (*(args[1]) == 0 || *(args[2]) == 0) {
3568 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3569 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
3573
3574 preg = calloc(1, sizeof(regex_t));
3575 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3576 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 }
3580
3581 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3582 if (err) {
3583 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3584 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
3588 }
3589 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3590 regex_t *preg;
3591 if (curproxy == &defproxy) {
3592 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003596 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003598
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 if (*(args[1]) == 0) {
3600 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 }
3604
3605 preg = calloc(1, sizeof(regex_t));
3606 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3607 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 }
3611
3612 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3613 if (err) {
3614 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3615 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 }
3619 }
3620 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3621 regex_t *preg;
3622 if (curproxy == &defproxy) {
3623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003627 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003629
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 if (*(args[1]) == 0) {
3631 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 }
3635
3636 preg = calloc(1, sizeof(regex_t));
3637 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3638 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 }
3642
3643 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3644 if (err) {
3645 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3646 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650 }
3651 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3652 if (curproxy == &defproxy) {
3653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003657 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659
3660 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3661 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 }
3665
3666 if (*(args[1]) == 0) {
3667 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
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 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3673 }
3674 else if (!strcmp(args[0], "errorloc") ||
3675 !strcmp(args[0], "errorloc302") ||
3676 !strcmp(args[0], "errorloc303")) { /* error location */
3677 int errnum, errlen;
3678 char *err;
3679
Willy Tarreau977b8e42006-12-29 14:19:17 +01003680 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003682
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003684 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 }
3688
3689 errnum = atol(args[1]);
3690 if (!strcmp(args[0], "errorloc303")) {
3691 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3692 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3693 } else {
3694 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3695 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3696 }
3697
Willy Tarreau0f772532006-12-23 20:51:41 +01003698 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3699 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003700 chunk_destroy(&curproxy->errmsg[rc]);
3701 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003702 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003705
3706 if (rc >= HTTP_ERR_SIZE) {
3707 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3708 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 free(err);
3710 }
3711 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003712 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3713 int errnum, errlen, fd;
3714 char *err;
3715 struct stat stat;
3716
3717 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003719
3720 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003721 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003724 }
3725
3726 fd = open(args[2], O_RDONLY);
3727 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3728 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3729 file, linenum, args[2], args[1]);
3730 if (fd >= 0)
3731 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003734 }
3735
Willy Tarreau27a674e2009-08-17 07:23:33 +02003736 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003737 errlen = stat.st_size;
3738 } else {
3739 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003740 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003742 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003743 }
3744
3745 err = malloc(errlen); /* malloc() must succeed during parsing */
3746 errnum = read(fd, err, errlen);
3747 if (errnum != errlen) {
3748 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3749 file, linenum, args[2], args[1]);
3750 close(fd);
3751 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003754 }
3755 close(fd);
3756
3757 errnum = atol(args[1]);
3758 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3759 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003760 chunk_destroy(&curproxy->errmsg[rc]);
3761 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003762 break;
3763 }
3764 }
3765
3766 if (rc >= HTTP_ERR_SIZE) {
3767 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3768 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003770 free(err);
3771 }
3772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003774 struct cfg_kw_list *kwl;
3775 int index;
3776
3777 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3778 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3779 if (kwl->kw[index].section != CFG_LISTEN)
3780 continue;
3781 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3782 /* prepare error message just in case */
3783 snprintf(trash, sizeof(trash),
3784 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003785 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3786 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003787 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003790 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003791 else if (rc > 0) {
3792 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_WARN;
3794 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003795 }
Willy Tarreau93893792009-07-23 13:19:11 +02003796 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003797 }
3798 }
3799 }
3800
Willy Tarreau6daf3432008-01-22 16:44:08 +01003801 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 }
Willy Tarreau93893792009-07-23 13:19:11 +02003805 out:
3806 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807}
3808
3809
3810/*
3811 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003812 * Returns the error code, 0 if OK, or any combination of :
3813 * - ERR_ABORT: must abort ASAP
3814 * - ERR_FATAL: we can continue parsing but not start the service
3815 * - ERR_WARN: a warning has been emitted
3816 * - ERR_ALERT: an alert has been emitted
3817 * Only the two first ones can stop processing, the two others are just
3818 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003820int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003822 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 FILE *f;
3824 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003826 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 if ((f=fopen(file,"r")) == NULL)
3829 return -1;
3830
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003831 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003832 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003833 char *end;
3834 char *args[MAX_LINE_ARGS + 1];
3835 char *line = thisline;
3836
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 linenum++;
3838
3839 end = line + strlen(line);
3840
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003841 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3842 /* Check if we reached the limit and the last char is not \n.
3843 * Watch out for the last line without the terminating '\n'!
3844 */
3845 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003846 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003848 }
3849
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003851 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 line++;
3853
3854 arg = 0;
3855 args[arg] = line;
3856
3857 while (*line && arg < MAX_LINE_ARGS) {
3858 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3859 * C equivalent value. Other combinations left unchanged (eg: \1).
3860 */
3861 if (*line == '\\') {
3862 int skip = 0;
3863 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3864 *line = line[1];
3865 skip = 1;
3866 }
3867 else if (line[1] == 'r') {
3868 *line = '\r';
3869 skip = 1;
3870 }
3871 else if (line[1] == 'n') {
3872 *line = '\n';
3873 skip = 1;
3874 }
3875 else if (line[1] == 't') {
3876 *line = '\t';
3877 skip = 1;
3878 }
3879 else if (line[1] == 'x') {
3880 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3881 unsigned char hex1, hex2;
3882 hex1 = toupper(line[2]) - '0';
3883 hex2 = toupper(line[3]) - '0';
3884 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3885 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3886 *line = (hex1<<4) + hex2;
3887 skip = 3;
3888 }
3889 else {
3890 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 }
3893 }
3894 if (skip) {
3895 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3896 end -= skip;
3897 }
3898 line++;
3899 }
3900 else if (*line == '#' || *line == '\n' || *line == '\r') {
3901 /* end of string, end of loop */
3902 *line = 0;
3903 break;
3904 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003905 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003907 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003908 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 line++;
3910 args[++arg] = line;
3911 }
3912 else {
3913 line++;
3914 }
3915 }
3916
3917 /* empty line */
3918 if (!**args)
3919 continue;
3920
Willy Tarreau540abe42007-05-02 20:50:16 +02003921 /* zero out remaining args and ensure that at least one entry
3922 * is zeroed out.
3923 */
3924 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 args[arg] = line;
3926 }
3927
Willy Tarreau3842f002009-06-14 11:39:52 +02003928 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003929 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003930 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003931 for (arg=0; *args[arg+1]; arg++)
3932 args[arg] = args[arg+1]; // shift args after inversion
3933 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003934 else if (!strcmp(args[0], "default")) {
3935 kwm = KWM_DEF;
3936 for (arg=0; *args[arg+1]; arg++)
3937 args[arg] = args[arg+1]; // shift args after inversion
3938 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003939
Willy Tarreau3842f002009-06-14 11:39:52 +02003940 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3941 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003942 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003943 }
3944
Willy Tarreau977b8e42006-12-29 14:19:17 +01003945 if (!strcmp(args[0], "listen") ||
3946 !strcmp(args[0], "frontend") ||
3947 !strcmp(args[0], "backend") ||
3948 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003949 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003951 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003952 cursection = strdup(args[0]);
3953 }
3954 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003956 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003957 cursection = strdup(args[0]);
3958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 /* else it's a section keyword */
3960
3961 switch (confsect) {
3962 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 break;
3965 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003966 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 break;
3968 default:
3969 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003972
3973 if (err_code & ERR_ABORT)
3974 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003976 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003977 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003979 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003980}
3981
Willy Tarreaubb925012009-07-23 13:36:36 +02003982/*
3983 * Returns the error code, 0 if OK, or any combination of :
3984 * - ERR_ABORT: must abort ASAP
3985 * - ERR_FATAL: we can continue parsing but not start the service
3986 * - ERR_WARN: a warning has been emitted
3987 * - ERR_ALERT: an alert has been emitted
3988 * Only the two first ones can stop processing, the two others are just
3989 * indicators.
3990 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003991int check_config_validity()
3992{
3993 int cfgerr = 0;
3994 struct proxy *curproxy = NULL;
3995 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003996 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003997 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998
3999 /*
4000 * Now, check for the integrity of all that we have collected.
4001 */
4002
4003 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004004 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004006 /* first, we will invert the proxy list order */
4007 curproxy = NULL;
4008 while (proxy) {
4009 struct proxy *next;
4010
4011 next = proxy->next;
4012 proxy->next = curproxy;
4013 curproxy = proxy;
4014 if (!next)
4015 break;
4016 proxy = next;
4017 }
4018
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004020 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 }
4024
4025 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004026 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004027 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004028 unsigned int next_id;
4029
4030 if (!curproxy->uuid) {
4031 /* proxy ID not set, use automatic numbering with first
4032 * spare entry starting with next_pxid.
4033 */
4034 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4035 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4036 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4037 next_pxid++;
4038 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004039
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004041 /* ensure we don't keep listeners uselessly bound */
4042 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043 curproxy = curproxy->next;
4044 continue;
4045 }
4046
Willy Tarreauff01a212009-03-15 13:46:16 +01004047 switch (curproxy->mode) {
4048 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004049 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004050 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004051 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4052 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004053 cfgerr++;
4054 }
4055
4056 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004057 Warning("config : servers will be ignored for %s '%s'.\n",
4058 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004059 break;
4060
4061 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004062 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004063 break;
4064
4065 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004066 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004067 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004068 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4069 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004070 cfgerr++;
4071 }
4072 break;
4073 }
4074
4075 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004076 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4077 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 cfgerr++;
4079 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004080
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004081 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004082 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004083 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004084 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4085 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004086 cfgerr++;
4087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004088#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004089 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004090 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4091 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004092 cfgerr++;
4093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004094#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004095 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004096 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4097 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004098 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004099 }
4100 }
4101 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4102 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4103 /* If no LB algo is set in a backend, and we're not in
4104 * transparent mode, dispatch mode nor proxy mode, we
4105 * want to use balance roundrobin by default.
4106 */
4107 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4108 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004109 }
4110 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004111
Willy Tarreau82936582007-11-30 15:20:09 +01004112 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4113 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004114 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4115 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004116 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004117 }
4118
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004119 /* if a default backend was specified, let's find it */
4120 if (curproxy->defbe.name) {
4121 struct proxy *target;
4122
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004123 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
4124 if (!target) {
4125 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4126 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004127 cfgerr++;
4128 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004129 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4130 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004131 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004132 } else {
4133 free(curproxy->defbe.name);
4134 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004135 /* we force the backend to be present on at least all of
4136 * the frontend's processes.
4137 */
4138 target->bind_proc = curproxy->bind_proc ?
4139 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 }
4141 }
4142
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004143 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004144 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4145 /* map jump target for ACT_SETBE in req_rep chain */
4146 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004147 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004148 struct proxy *target;
4149
Willy Tarreaua496b602006-12-17 23:15:24 +01004150 if (exp->action != ACT_SETBE)
4151 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004152
4153 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
4154 if (!target) {
4155 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4156 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004157 cfgerr++;
4158 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004159 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4160 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004161 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004162 } else {
4163 free((void *)exp->replace);
4164 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004165 /* we force the backend to be present on at least all of
4166 * the frontend's processes.
4167 */
4168 target->bind_proc = curproxy->bind_proc ?
4169 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004170 }
4171 }
4172 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004173
4174 /* find the target proxy for 'use_backend' rules */
4175 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004176 struct proxy *target;
4177
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004178 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004179
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004180 if (!target) {
4181 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4182 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004183 cfgerr++;
4184 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004185 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4186 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004187 cfgerr++;
4188 } else {
4189 free((void *)rule->be.name);
4190 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004191 /* we force the backend to be present on at least all of
4192 * the frontend's processes.
4193 */
4194 target->bind_proc = curproxy->bind_proc ?
4195 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004196 }
4197 }
4198
Willy Tarreau2738a142006-07-08 17:28:09 +02004199 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004200 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004201 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004202 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004203 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004204 " | While not properly invalid, you will certainly encounter various problems\n"
4205 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004206 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004207 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004208 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004209 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004210
Willy Tarreau1fa31262007-12-03 00:36:16 +01004211 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4212 * We must still support older configurations, so let's find out whether those
4213 * parameters have been set or must be copied from contimeouts.
4214 */
4215 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004216 if (!curproxy->timeout.tarpit ||
4217 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004218 /* tarpit timeout not set. We search in the following order:
4219 * default.tarpit, curr.connect, default.connect.
4220 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004221 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004222 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004223 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004224 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004225 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004226 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004227 }
4228 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004229 (!curproxy->timeout.queue ||
4230 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004231 /* queue timeout not set. We search in the following order:
4232 * default.queue, curr.connect, default.connect.
4233 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004234 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004235 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004236 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004237 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004238 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004239 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004240 }
4241 }
4242
Willy Tarreauf3c69202006-07-09 16:42:34 +02004243 if (curproxy->options & PR_O_SSL3_CHK) {
4244 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4245 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4246 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4247 }
4248
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004249 /* The small pools required for the capture lists */
4250 if (curproxy->nb_req_cap)
4251 curproxy->req_cap_pool = create_pool("ptrcap",
4252 curproxy->nb_req_cap * sizeof(char *),
4253 MEM_F_SHARED);
4254 if (curproxy->nb_rsp_cap)
4255 curproxy->rsp_cap_pool = create_pool("ptrcap",
4256 curproxy->nb_rsp_cap * sizeof(char *),
4257 MEM_F_SHARED);
4258
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004259 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4260 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4261 MEM_F_SHARED);
4262
Willy Tarreau86034312006-12-29 00:10:33 +01004263 /* for backwards compatibility with "listen" instances, if
4264 * fullconn is not set but maxconn is set, then maxconn
4265 * is used.
4266 */
4267 if (!curproxy->fullconn)
4268 curproxy->fullconn = curproxy->maxconn;
4269
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 /* first, we will invert the servers list order */
4271 newsrv = NULL;
4272 while (curproxy->srv) {
4273 struct server *next;
4274
4275 next = curproxy->srv->next;
4276 curproxy->srv->next = newsrv;
4277 newsrv = curproxy->srv;
4278 if (!next)
4279 break;
4280 curproxy->srv = next;
4281 }
4282
Willy Tarreau20697042007-11-15 23:26:18 +01004283 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004284 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004286 /* We have to initialize the server lookup mechanism depending
4287 * on what LB algorithm was choosen.
4288 */
4289
4290 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4291 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4292 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004293 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4294 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4295 init_server_map(curproxy);
4296 } else {
4297 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4298 fwrr_init_server_groups(curproxy);
4299 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004300 break;
4301 case BE_LB_KIND_LC:
4302 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004303 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004304 break;
4305 case BE_LB_KIND_HI:
4306 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
Willy Tarreaub625a082007-11-26 01:15:43 +01004307 init_server_map(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004308 break;
4309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310
4311 if (curproxy->options & PR_O_LOGASAP)
4312 curproxy->to_log &= ~LW_BYTES;
4313
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004314 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4315 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4316 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4317 proxy_type_str(curproxy), curproxy->id);
4318 err_code |= ERR_WARN;
4319 }
4320
Willy Tarreaubaaee002006-06-26 02:48:02 +02004321 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004322 * ensure that we're not cross-dressing a TCP server into HTTP.
4323 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004324 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004325 newsrv = curproxy->srv;
4326 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004327 if (!newsrv->puid) {
4328 /* server ID not set, use automatic numbering with first
4329 * spare entry starting with next_svid.
4330 */
4331 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4332 newsrv->conf.id.key = newsrv->puid = next_id;
4333 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4334 next_id++;
4335 }
4336
Willy Tarreau21d2af32008-02-14 20:25:24 +01004337 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004338 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4339 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004340 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004341 }
4342 newsrv = newsrv->next;
4343 }
4344
4345 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 * If this server supports a maxconn parameter, it needs a dedicated
4347 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004348 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 */
4350 newsrv = curproxy->srv;
4351 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004352 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 /* Only 'minconn' was specified, or it was higher than or equal
4354 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4355 * this will avoid further useless expensive computations.
4356 */
4357 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004358 } else if (newsrv->maxconn && !newsrv->minconn) {
4359 /* minconn was not specified, so we set it to maxconn */
4360 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004361 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004362 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4363 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004364 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 }
4366
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004367 if (newsrv->trackit) {
4368 struct proxy *px;
4369 struct server *srv;
4370 char *pname, *sname;
4371
4372 pname = newsrv->trackit;
4373 sname = strrchr(pname, '/');
4374
4375 if (sname)
4376 *sname++ = '\0';
4377 else {
4378 sname = pname;
4379 pname = NULL;
4380 }
4381
4382 if (pname) {
4383 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4384 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004385 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4386 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004387 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004388 cfgerr++;
4389 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004390 }
4391 } else
4392 px = curproxy;
4393
4394 srv = findserver(px, sname);
4395 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004396 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4397 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004398 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004399 cfgerr++;
4400 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004401 }
4402
4403 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004404 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004405 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004406 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004407 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004408 cfgerr++;
4409 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004410 }
4411
4412 if (curproxy != px &&
4413 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004414 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004415 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004416 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004417 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004418 cfgerr++;
4419 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004420 }
4421
4422 newsrv->tracked = srv;
4423 newsrv->tracknext = srv->tracknext;
4424 srv->tracknext = newsrv;
4425
4426 free(newsrv->trackit);
4427 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004428 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004429 newsrv = newsrv->next;
4430 }
4431
Willy Tarreauc1a21672009-08-16 22:37:44 +02004432 if (curproxy->cap & PR_CAP_FE) {
4433 if (curproxy->tcp_req.inspect_delay ||
4434 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4435 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4436
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004437 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004438 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004439 curproxy->fe_rsp_ana |= AN_RTR_HTTP_HDR;
4440 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004441
4442 /* both TCP and HTTP must check switching rules */
4443 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4444 }
4445
4446 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004447 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004448 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004449 curproxy->be_rsp_ana |= AN_RTR_HTTP_HDR;
4450 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004451
4452 /* If the backend does requires RDP cookie persistence, we have to
4453 * enable the corresponding analyser.
4454 */
4455 if (curproxy->options2 & PR_O2_RDPC_PRST)
4456 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4457 }
4458
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004459 listener = NULL;
4460 while (curproxy->listen) {
4461 struct listener *next;
4462
4463 next = curproxy->listen->next;
4464 curproxy->listen->next = listener;
4465 listener = curproxy->listen;
4466
4467 if (!next)
4468 break;
4469
4470 curproxy->listen = next;
4471 }
4472
Willy Tarreaue6b98942007-10-29 01:09:36 +01004473 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004474 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004475 listener = curproxy->listen;
4476 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004477 if (!listener->luid) {
4478 /* listener ID not set, use automatic numbering with first
4479 * spare entry starting with next_luid.
4480 */
4481 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4482 listener->conf.id.key = listener->luid = next_id;
4483 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4484 next_id++;
4485 }
4486
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004487 /* enable separate counters */
4488 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4489 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4490 if (!listener->name) {
4491 sprintf(trash, "sock-%d", listener->luid);
4492 listener->name = strdup(trash);
4493 }
4494 }
4495
Willy Tarreaue6b98942007-10-29 01:09:36 +01004496 if (curproxy->options & PR_O_TCP_NOLING)
4497 listener->options |= LI_O_NOLINGER;
4498 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004499 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004500 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004501 listener->accept = event_accept;
4502 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004503 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004504 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004505
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004506 /* smart accept mode is automatic in HTTP mode */
4507 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4508 (curproxy->mode == PR_MODE_HTTP &&
4509 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4510 listener->options |= LI_O_NOQUICKACK;
4511
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004512 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004513 listener = listener->next;
4514 }
4515
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 curproxy = curproxy->next;
4517 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004518
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004519 /*
4520 * Recount currently required checks.
4521 */
4522
4523 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4524 int optnum;
4525
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004526 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4527 if (curproxy->options & cfg_opts[optnum].val)
4528 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004529
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004530 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4531 if (curproxy->options2 & cfg_opts2[optnum].val)
4532 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004533 }
4534
Willy Tarreaubb925012009-07-23 13:36:36 +02004535 if (cfgerr > 0)
4536 err_code |= ERR_ALERT | ERR_FATAL;
4537 out:
4538 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004539}
4540
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004541/*
4542 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4543 * parsing sessions.
4544 */
4545void cfg_register_keywords(struct cfg_kw_list *kwl)
4546{
4547 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4548}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004550/*
4551 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4552 */
4553void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4554{
4555 LIST_DEL(&kwl->list);
4556 LIST_INIT(&kwl->list);
4557}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558
4559/*
4560 * Local variables:
4561 * c-indent-level: 8
4562 * c-basic-offset: 8
4563 * End:
4564 */