blob: 38dd8eb1ca6cf49f8ee96e55763d733be977b836 [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
261 l->luid = curproxy->next_lid++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100262 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 } /* end for(port) */
264 } /* end while(next) */
265 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 fail:
268 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270}
271
Willy Tarreau977b8e42006-12-29 14:19:17 +0100272/*
273 * Sends a warning if proxy <proxy> does not have at least one of the
274 * capabilities in <cap>. An optionnal <hint> may be added at the end
275 * of the warning to help the user. Returns 1 if a warning was emitted
276 * or 0 if the condition is valid.
277 */
278int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
279{
280 char *msg;
281
282 switch (cap) {
283 case PR_CAP_BE: msg = "no backend"; break;
284 case PR_CAP_FE: msg = "no frontend"; break;
285 case PR_CAP_RS: msg = "no ruleset"; break;
286 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
287 default: msg = "not enough"; break;
288 }
289
290 if (!(proxy->cap & cap)) {
291 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100292 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100293 return 1;
294 }
295 return 0;
296}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297
Willy Tarreau61d18892009-03-31 10:49:21 +0200298/* Report a warning if a rule is placed after a 'block' rule.
299 * Return 1 if the warning has been emitted, otherwise 0.
300 */
301int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
302{
303 if (!LIST_ISEMPTY(&proxy->block_cond)) {
304 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
305 file, line, arg);
306 return 1;
307 }
308 return 0;
309}
310
311/* Report a warning if a rule is placed after a reqrewrite rule.
312 * Return 1 if the warning has been emitted, otherwise 0.
313 */
314int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
315{
316 if (proxy->req_exp) {
317 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
318 file, line, arg);
319 return 1;
320 }
321 return 0;
322}
323
324/* Report a warning if a rule is placed after a reqadd rule.
325 * Return 1 if the warning has been emitted, otherwise 0.
326 */
327int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
328{
329 if (proxy->nb_reqadd) {
330 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
331 file, line, arg);
332 return 1;
333 }
334 return 0;
335}
336
337/* Report a warning if a rule is placed after a redirect rule.
338 * Return 1 if the warning has been emitted, otherwise 0.
339 */
340int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
341{
342 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
343 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
344 file, line, arg);
345 return 1;
346 }
347 return 0;
348}
349
350/* Report a warning if a rule is placed after a 'use_backend' rule.
351 * Return 1 if the warning has been emitted, otherwise 0.
352 */
353int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
354{
355 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
356 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
357 file, line, arg);
358 return 1;
359 }
360 return 0;
361}
362
363/* report a warning if a block rule is dangerously placed */
364int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
365{
366 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
367 warnif_rule_after_reqadd(proxy, file, line, arg) ||
368 warnif_rule_after_redirect(proxy, file, line, arg) ||
369 warnif_rule_after_use_backend(proxy, file, line, arg);
370}
371
372/* report a warning if a reqxxx rule is dangerously placed */
373int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
374{
375 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
376 warnif_rule_after_redirect(proxy, file, line, arg) ||
377 warnif_rule_after_use_backend(proxy, file, line, arg);
378}
379
380/* report a warning if a reqadd rule is dangerously placed */
381int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
382{
383 return warnif_rule_after_redirect(proxy, file, line, arg) ||
384 warnif_rule_after_use_backend(proxy, file, line, arg);
385}
386
Willy Tarreaubaaee002006-06-26 02:48:02 +0200387/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200388 * parse a line in a <global> section. Returns the error code, 0 if OK, or
389 * any combination of :
390 * - ERR_ABORT: must abort ASAP
391 * - ERR_FATAL: we can continue parsing but not start the service
392 * - ERR_WARN: a warning has been emitted
393 * - ERR_ALERT: an alert has been emitted
394 * Only the two first ones can stop processing, the two others are just
395 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200396 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200397int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200398{
Willy Tarreau058e9072009-07-20 09:30:05 +0200399 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200400
401 if (!strcmp(args[0], "global")) { /* new section */
402 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200404 }
405 else if (!strcmp(args[0], "daemon")) {
406 global.mode |= MODE_DAEMON;
407 }
408 else if (!strcmp(args[0], "debug")) {
409 global.mode |= MODE_DEBUG;
410 }
411 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100412 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200413 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200414 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100415 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200416 }
417 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100418 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200420 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100421 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200422 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100423 else if (!strcmp(args[0], "nosplice")) {
424 global.tune.options &= ~GTUNE_USE_SPLICE;
425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 else if (!strcmp(args[0], "quiet")) {
427 global.mode |= MODE_QUIET;
428 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200429 else if (!strcmp(args[0], "tune.maxpollevents")) {
430 if (global.tune.maxpollevents != 0) {
431 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200432 err_code |= ERR_ALERT;
433 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200434 }
435 if (*(args[1]) == 0) {
436 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200437 err_code |= ERR_ALERT | ERR_FATAL;
438 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200439 }
440 global.tune.maxpollevents = atol(args[1]);
441 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100442 else if (!strcmp(args[0], "tune.maxaccept")) {
443 if (global.tune.maxaccept != 0) {
444 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 err_code |= ERR_ALERT;
446 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100447 }
448 if (*(args[1]) == 0) {
449 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 err_code |= ERR_ALERT | ERR_FATAL;
451 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100452 }
453 global.tune.maxaccept = atol(args[1]);
454 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200455 else if (!strcmp(args[0], "tune.bufsize")) {
456 if (*(args[1]) == 0) {
457 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
458 err_code |= ERR_ALERT | ERR_FATAL;
459 goto out;
460 }
461 global.tune.bufsize = atol(args[1]);
462 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
463 global.tune.maxrewrite = global.tune.bufsize / 2;
464 }
465 else if (!strcmp(args[0], "tune.maxrewrite")) {
466 if (*(args[1]) == 0) {
467 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
468 err_code |= ERR_ALERT | ERR_FATAL;
469 goto out;
470 }
471 global.tune.maxrewrite = atol(args[1]);
472 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
473 global.tune.maxrewrite = global.tune.bufsize / 2;
474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "uid")) {
476 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200477 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200478 err_code |= ERR_ALERT;
479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 }
481 if (*(args[1]) == 0) {
482 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 }
486 global.uid = atol(args[1]);
487 }
488 else if (!strcmp(args[0], "gid")) {
489 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200490 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200491 err_code |= ERR_ALERT;
492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 }
499 global.gid = atol(args[1]);
500 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200501 /* user/group name handling */
502 else if (!strcmp(args[0], "user")) {
503 struct passwd *ha_user;
504 if (global.uid != 0) {
505 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200506 err_code |= ERR_ALERT;
507 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200508 }
509 errno = 0;
510 ha_user = getpwnam(args[1]);
511 if (ha_user != NULL) {
512 global.uid = (int)ha_user->pw_uid;
513 }
514 else {
515 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 +0200516 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200517 }
518 }
519 else if (!strcmp(args[0], "group")) {
520 struct group *ha_group;
521 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200522 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200523 err_code |= ERR_ALERT;
524 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200525 }
526 errno = 0;
527 ha_group = getgrnam(args[1]);
528 if (ha_group != NULL) {
529 global.gid = (int)ha_group->gr_gid;
530 }
531 else {
532 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 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200534 }
535 }
536 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200537 else if (!strcmp(args[0], "nbproc")) {
538 if (global.nbproc != 0) {
539 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200540 err_code |= ERR_ALERT;
541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542 }
543 if (*(args[1]) == 0) {
544 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200545 err_code |= ERR_ALERT | ERR_FATAL;
546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 }
548 global.nbproc = atol(args[1]);
549 }
550 else if (!strcmp(args[0], "maxconn")) {
551 if (global.maxconn != 0) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200553 err_code |= ERR_ALERT;
554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 }
561 global.maxconn = atol(args[1]);
562#ifdef SYSTEM_MAXCONN
563 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
564 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);
565 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200566 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 }
568#endif /* SYSTEM_MAXCONN */
569 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100570 else if (!strcmp(args[0], "maxpipes")) {
571 if (global.maxpipes != 0) {
572 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200573 err_code |= ERR_ALERT;
574 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100580 }
581 global.maxpipes = atol(args[1]);
582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583 else if (!strcmp(args[0], "ulimit-n")) {
584 if (global.rlimit_nofile != 0) {
585 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 err_code |= ERR_ALERT;
587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 }
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 }
594 global.rlimit_nofile = atol(args[1]);
595 }
596 else if (!strcmp(args[0], "chroot")) {
597 if (global.chroot != NULL) {
598 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200599 err_code |= ERR_ALERT;
600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
602 if (*(args[1]) == 0) {
603 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 }
607 global.chroot = strdup(args[1]);
608 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200609 else if (!strcmp(args[0], "description")) {
610 int i, len=0;
611 char *d;
612
613 if (!*args[1]) {
614 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
615 file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619
620 for(i=1; *args[i]; i++)
621 len += strlen(args[i])+1;
622
623 if (global.desc)
624 free(global.desc);
625
626 global.desc = d = (char *)calloc(1, len);
627
628 d += sprintf(d, "%s", args[1]);
629 for(i=2; *args[i]; i++)
630 d += sprintf(d, " %s", args[i]);
631 }
632 else if (!strcmp(args[0], "node")) {
633 int i;
634 char c;
635
636 for (i=0; args[1][i]; i++) {
637 c = args[1][i];
638 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
639 break;
640 }
641
642 if (!i || args[1][i]) {
643 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
644 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
645 file, linenum, args[0]);
646 err_code |= ERR_ALERT | ERR_FATAL;
647 goto out;
648 }
649
650 if (global.node)
651 free(global.node);
652
653 global.node = strdup(args[1]);
654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655 else if (!strcmp(args[0], "pidfile")) {
656 if (global.pidfile != NULL) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 }
666 global.pidfile = strdup(args[1]);
667 }
668 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100669 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200670 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671
672 if (*(args[1]) == 0 || *(args[2]) == 0) {
673 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 }
677
678 facility = get_log_facility(args[2]);
679 if (facility < 0) {
680 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT | ERR_FATAL;
682 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684
685 level = 7; /* max syslog level = debug */
686 if (*(args[3])) {
687 level = get_log_level(args[3]);
688 if (level < 0) {
689 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT | ERR_FATAL;
691 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 }
694
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200695 minlvl = 0; /* limit syslog level to this level (emerg) */
696 if (*(args[4])) {
697 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200699 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200700 err_code |= ERR_ALERT | ERR_FATAL;
701 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200702 }
703 }
704
Robert Tsai81ae1952007-12-05 10:47:29 +0100705 if (args[1][0] == '/') {
706 logsrv.u.addr.sa_family = AF_UNIX;
707 logsrv.u.un = *str2sun(args[1]);
708 } else {
709 logsrv.u.addr.sa_family = AF_INET;
710 logsrv.u.in = *str2sa(args[1]);
711 if (!logsrv.u.in.sin_port)
712 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714
715 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100716 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717 global.logfac1 = facility;
718 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200719 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 }
721 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100722 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 global.logfac2 = facility;
724 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200725 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 }
727 else {
728 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200731 }
732 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
733 if (global.spread_checks != 0) {
734 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200735 err_code |= ERR_ALERT;
736 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200737 }
738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200742 }
743 global.spread_checks = atol(args[1]);
744 if (global.spread_checks < 0 || global.spread_checks > 50) {
745 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200746 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 }
749 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200750 struct cfg_kw_list *kwl;
751 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200752 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200753
754 list_for_each_entry(kwl, &cfg_keywords.list, list) {
755 for (index = 0; kwl->kw[index].kw != NULL; index++) {
756 if (kwl->kw[index].section != CFG_GLOBAL)
757 continue;
758 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
759 /* prepare error message just in case */
760 snprintf(trash, sizeof(trash),
761 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200762 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
763 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200764 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200766 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200767 else if (rc > 0) {
768 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_WARN;
770 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200771 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200772 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200773 }
774 }
775 }
776
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200780
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 out:
782 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783}
784
785
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200786void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787{
788 memset(&defproxy, 0, sizeof(defproxy));
789 defproxy.mode = PR_MODE_TCP;
790 defproxy.state = PR_STNEW;
791 defproxy.maxconn = cfg_maxpconn;
792 defproxy.conn_retries = CONN_RETRIES;
793 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200794
795 LIST_INIT(&defproxy.pendconns);
796 LIST_INIT(&defproxy.acl);
797 LIST_INIT(&defproxy.block_cond);
798 LIST_INIT(&defproxy.mon_fail_cond);
799 LIST_INIT(&defproxy.switching_rules);
800
Willy Tarreau3a70f942008-02-15 11:15:34 +0100801 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802}
803
804/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100805 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200806 * Returns the error code, 0 if OK, or any combination of :
807 * - ERR_ABORT: must abort ASAP
808 * - ERR_FATAL: we can continue parsing but not start the service
809 * - ERR_WARN: a warning has been emitted
810 * - ERR_ALERT: an alert has been emitted
811 * Only the two first ones can stop processing, the two others are just
812 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200814int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815{
816 static struct proxy *curproxy = NULL;
817 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200818 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100819 int rc;
820 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200821 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822
Willy Tarreau977b8e42006-12-29 14:19:17 +0100823 if (!strcmp(args[0], "listen"))
824 rc = PR_CAP_LISTEN;
825 else if (!strcmp(args[0], "frontend"))
826 rc = PR_CAP_FE | PR_CAP_RS;
827 else if (!strcmp(args[0], "backend"))
828 rc = PR_CAP_BE | PR_CAP_RS;
829 else if (!strcmp(args[0], "ruleset"))
830 rc = PR_CAP_RS;
831 else
832 rc = PR_CAP_NONE;
833
834 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 if (!*args[1]) {
836 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
837 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
838 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200839 err_code |= ERR_ALERT | ERR_ABORT;
840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200842
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100843 err = invalid_char(args[1]);
844 if (err) {
845 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
846 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100848 }
849
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200850 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
851 /*
852 * If there are two proxies with the same name only following
853 * combinations are allowed:
854 *
855 * listen backend frontend ruleset
856 * listen - - - -
857 * backend - - OK -
858 * frontend - OK - -
859 * ruleset - - - -
860 */
861
862 if (!strcmp(curproxy->id, args[1]) &&
863 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
864 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100865 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
866 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
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 Tarreaudcd47712007-11-04 23:35:08 +01001015 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
1016 curproxy->next_svid = 1; /* server id 0 is reserved */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001017 curproxy->next_lid = 1; /* listener id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +02001018
Willy Tarreau93893792009-07-23 13:19:11 +02001019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1022 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001023 /* FIXME-20070101: we should do this too at the end of the
1024 * config parsing to free all default values.
1025 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001026 free(defproxy.check_req);
1027 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001028 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001029 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001030 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001031 free(defproxy.capture_name);
1032 free(defproxy.monitor_uri);
1033 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001034 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001035 free(defproxy.fwdfor_hdr_name);
1036 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001037
Willy Tarreaua534fea2008-08-03 12:19:50 +02001038 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001039 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001040
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 /* we cannot free uri_auth because it might already be used */
1042 init_default_instance();
1043 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001044 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 }
1047 else if (curproxy == NULL) {
1048 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052
Willy Tarreau977b8e42006-12-29 14:19:17 +01001053
1054 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001056 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001057 int cur_arg;
1058
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 if (curproxy == &defproxy) {
1060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001064 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001065 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066
1067 if (strchr(args[1], ':') == NULL) {
1068 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001073
1074 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001075 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001079
Willy Tarreau90a570f2009-10-04 20:54:54 +02001080 new_listen = curproxy->listen;
1081 while (new_listen != last_listen) {
1082 new_listen->conf.file = file;
1083 new_listen->conf.line = linenum;
1084 new_listen = new_listen->next;
1085 }
1086
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001087 cur_arg = 2;
1088 while (*(args[cur_arg])) {
1089 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1090#ifdef SO_BINDTODEVICE
1091 struct listener *l;
1092
1093 if (!*args[cur_arg + 1]) {
1094 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001098 }
1099
1100 for (l = curproxy->listen; l != last_listen; l = l->next)
1101 l->interface = strdup(args[cur_arg + 1]);
1102
1103 global.last_checks |= LSTCHK_NETADM;
1104
1105 cur_arg += 2;
1106 continue;
1107#else
1108 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1109 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001112#endif
1113 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001114 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1115#ifdef TCP_MAXSEG
1116 struct listener *l;
1117 int mss;
1118
1119 if (!*args[cur_arg + 1]) {
1120 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1121 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001124 }
1125
1126 mss = str2uic(args[cur_arg + 1]);
1127 if (mss < 1 || mss > 65535) {
1128 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1129 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001132 }
1133
1134 for (l = curproxy->listen; l != last_listen; l = l->next)
1135 l->maxseg = mss;
1136
1137 cur_arg += 2;
1138 continue;
1139#else
1140 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1141 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001144#endif
1145 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001146 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001147#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001148 struct listener *l;
1149
1150 for (l = curproxy->listen; l != last_listen; l = l->next)
1151 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001152
1153 cur_arg ++;
1154 continue;
1155#else
1156 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1157 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001160#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001161 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001162
1163 if (!strcmp(args[cur_arg], "name")) {
1164 struct listener *l;
1165
1166 for (l = curproxy->listen; l != last_listen; l = l->next)
1167 l->name = strdup(args[cur_arg + 1]);
1168
1169 cur_arg += 2;
1170 continue;
1171 }
1172
1173 if (!strcmp(args[cur_arg], "id")) {
1174 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]);
1191
1192 if (curproxy->listen->luid < 1001) {
1193 Alert("parsing [%s:%d]: custom id has to be > 1000\n",
1194 file, linenum);
1195 err_code |= ERR_ALERT | ERR_FATAL;
1196 goto out;
1197 }
1198
Willy Tarreau9d7e3352009-10-04 21:13:39 +02001199 for (l = curproxy->listen; l; l = l->next)
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001200 if (curproxy->listen != l && l->luid == curproxy->listen->luid) {
1201 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s.\n",
1202 file, linenum, args[1]);
1203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
1205 }
1206 cur_arg += 2;
1207 continue;
1208 }
1209
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001210 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001211 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1219 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1220 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1221 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001225 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001226 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001227
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 /* flush useless bits */
1229 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001232 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001233 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001234 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001235
Willy Tarreau1c47f852006-07-09 08:22:27 +02001236 if (!*args[1]) {
1237 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1238 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001239 err_code |= ERR_ALERT | ERR_FATAL;
1240 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001241 }
1242
Willy Tarreaua534fea2008-08-03 12:19:50 +02001243 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001244 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001245 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001246 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001247 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1248
Willy Tarreau93893792009-07-23 13:19:11 +02001249 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1252 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1253 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1254 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1255 else {
1256 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001259 }
1260 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001261 else if (!strcmp(args[0], "id")) {
1262 struct proxy *target;
1263
1264 if (curproxy == &defproxy) {
1265 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1266 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001269 }
1270
1271 if (!*args[1]) {
1272 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1273 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001276 }
1277
1278 curproxy->uuid = atol(args[1]);
1279
1280 if (curproxy->uuid < 1001) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02001281 Alert("parsing [%s:%d]: custom id has to be > 1000.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001282 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001285 }
1286
1287 for (target = proxy; target; target = target->next)
1288 if (curproxy != target && curproxy->uuid == target->uuid) {
1289 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1290 file, linenum, curproxy->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001293 }
1294 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001295 else if (!strcmp(args[0], "description")) {
1296 int i, len=0;
1297 char *d;
1298
1299 if (!*args[1]) {
1300 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1301 file, linenum, args[0]);
1302 return -1;
1303 }
1304
1305 for(i=1; *args[i]; i++)
1306 len += strlen(args[i])+1;
1307
1308 d = (char *)calloc(1, len);
1309 curproxy->desc = d;
1310
1311 d += sprintf(d, "%s", args[1]);
1312 for(i=2; *args[i]; i++)
1313 d += sprintf(d, " %s", args[i]);
1314
1315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1317 curproxy->state = PR_STSTOPPED;
1318 }
1319 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1320 curproxy->state = PR_STNEW;
1321 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001322 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1323 int cur_arg = 1;
1324 unsigned int set = 0;
1325
1326 while (*args[cur_arg]) {
1327 int u;
1328 if (strcmp(args[cur_arg], "all") == 0) {
1329 set = 0;
1330 break;
1331 }
1332 else if (strcmp(args[cur_arg], "odd") == 0) {
1333 set |= 0x55555555;
1334 }
1335 else if (strcmp(args[cur_arg], "even") == 0) {
1336 set |= 0xAAAAAAAA;
1337 }
1338 else {
1339 u = str2uic(args[cur_arg]);
1340 if (u < 1 || u > 32) {
1341 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001345 }
1346 if (u > global.nbproc) {
1347 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001349 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001350 }
1351 set |= 1 << (u - 1);
1352 }
1353 cur_arg++;
1354 }
1355 curproxy->bind_proc = set;
1356 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001357 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001358 if (curproxy == &defproxy) {
1359 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001362 }
1363
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001364 err = invalid_char(args[1]);
1365 if (err) {
1366 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1367 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001368 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001369 }
1370
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001371 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1372 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1373 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001376 }
1377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1379 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380
Willy Tarreau977b8e42006-12-29 14:19:17 +01001381 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001383
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 if (*(args[1]) == 0) {
1385 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001390
1391 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 curproxy->cookie_name = strdup(args[1]);
1393 curproxy->cookie_len = strlen(curproxy->cookie_name);
1394
1395 cur_arg = 2;
1396 while (*(args[cur_arg])) {
1397 if (!strcmp(args[cur_arg], "rewrite")) {
1398 curproxy->options |= PR_O_COOK_RW;
1399 }
1400 else if (!strcmp(args[cur_arg], "indirect")) {
1401 curproxy->options |= PR_O_COOK_IND;
1402 }
1403 else if (!strcmp(args[cur_arg], "insert")) {
1404 curproxy->options |= PR_O_COOK_INS;
1405 }
1406 else if (!strcmp(args[cur_arg], "nocache")) {
1407 curproxy->options |= PR_O_COOK_NOC;
1408 }
1409 else if (!strcmp(args[cur_arg], "postonly")) {
1410 curproxy->options |= PR_O_COOK_POST;
1411 }
1412 else if (!strcmp(args[cur_arg], "prefix")) {
1413 curproxy->options |= PR_O_COOK_PFX;
1414 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001415 else if (!strcmp(args[cur_arg], "domain")) {
1416 if (!*args[cur_arg + 1]) {
1417 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1418 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001421 }
1422
1423 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1424 /* rfc2109, 4.3.2 Rejecting Cookies */
1425 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1426 " dots or does not start with a dot.\n",
1427 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001428 err_code |= ERR_ALERT | ERR_FATAL;
1429 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001430 }
1431
1432 err = invalid_domainchar(args[cur_arg + 1]);
1433 if (err) {
1434 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1435 file, linenum, *err, 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
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001440 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001441 cur_arg++;
1442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001444 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
1449 cur_arg++;
1450 }
1451 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1452 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1453 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001454 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 }
1456
1457 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1458 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1459 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001460 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 }
1462 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001463 else if (!strcmp(args[0], "persist")) { /* persist */
1464 if (*(args[1]) == 0) {
1465 Alert("parsing [%s:%d] : missing persist method.\n",
1466 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001467 err_code |= ERR_ALERT | ERR_FATAL;
1468 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001469 }
1470
1471 if (!strncmp(args[1], "rdp-cookie", 10)) {
1472 curproxy->options2 |= PR_O2_RDPC_PRST;
1473
1474 if (*(args[1] + 10 ) == '(') { /* cookie name */
1475 const char *beg, *end;
1476
1477 beg = args[1] + 11;
1478 end = strchr(beg, ')');
1479
1480 if (!end || end == beg) {
1481 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1482 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001485 }
1486
1487 free(curproxy->rdp_cookie_name);
1488 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1489 curproxy->rdp_cookie_len = end-beg;
1490 }
1491 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1492 free(curproxy->rdp_cookie_name);
1493 curproxy->rdp_cookie_name = strdup("msts");
1494 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1495 }
1496 else { /* syntax */
1497 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1498 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001501 }
1502 }
1503 else {
1504 Alert("parsing [%s:%d] : unknown persist method.\n",
1505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001508 }
1509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001513 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 if (*(args[5]) == 0) {
1516 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1517 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 }
1521 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001522 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 curproxy->appsession_name = strdup(args[1]);
1524 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1525 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001526 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1527 if (err) {
1528 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1529 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001532 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001533 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001534
Willy Tarreau51041c72007-09-09 21:56:53 +02001535 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1536 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001537 err_code |= ERR_ALERT | ERR_ABORT;
1538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539 }
1540 } /* Url App Session */
1541 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001542 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001543 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001544
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001546 if (*(args[4]) == 0) {
1547 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1548 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001552 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 curproxy->capture_name = strdup(args[2]);
1554 curproxy->capture_namelen = strlen(curproxy->capture_name);
1555 curproxy->capture_len = atol(args[4]);
1556 if (curproxy->capture_len >= CAPTURE_LEN) {
1557 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1558 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001559 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 curproxy->capture_len = CAPTURE_LEN - 1;
1561 }
1562 curproxy->to_log |= LW_COOKIE;
1563 }
1564 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1565 struct cap_hdr *hdr;
1566
1567 if (curproxy == &defproxy) {
1568 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 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
1572
1573 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1574 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1575 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
1579
1580 hdr = calloc(sizeof(struct cap_hdr), 1);
1581 hdr->next = curproxy->req_cap;
1582 hdr->name = strdup(args[3]);
1583 hdr->namelen = strlen(args[3]);
1584 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001585 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 hdr->index = curproxy->nb_req_cap++;
1587 curproxy->req_cap = hdr;
1588 curproxy->to_log |= LW_REQHDR;
1589 }
1590 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1591 struct cap_hdr *hdr;
1592
1593 if (curproxy == &defproxy) {
1594 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 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 }
1598
1599 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1600 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1601 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001602 err_code |= ERR_ALERT | ERR_FATAL;
1603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 }
1605 hdr = calloc(sizeof(struct cap_hdr), 1);
1606 hdr->next = curproxy->rsp_cap;
1607 hdr->name = strdup(args[3]);
1608 hdr->namelen = strlen(args[3]);
1609 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001610 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 hdr->index = curproxy->nb_rsp_cap++;
1612 curproxy->rsp_cap = hdr;
1613 curproxy->to_log |= LW_RSPHDR;
1614 }
1615 else {
1616 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1617 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
1619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 }
1621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001623 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001625
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 if (*(args[1]) == 0) {
1627 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 }
1632 curproxy->conn_retries = atol(args[1]);
1633 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001634 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1635 int pol = ACL_COND_NONE;
1636 struct acl_cond *cond;
1637
Willy Tarreaub099aca2008-10-12 17:26:37 +02001638 if (curproxy == &defproxy) {
1639 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001640 err_code |= ERR_ALERT | ERR_FATAL;
1641 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001642 }
1643
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001644 if (!strcmp(args[1], "if"))
1645 pol = ACL_COND_IF;
1646 else if (!strcmp(args[1], "unless"))
1647 pol = ACL_COND_UNLESS;
1648
1649 if (pol == ACL_COND_NONE) {
1650 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001654 }
1655
1656 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1657 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1658 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001661 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001662 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001663 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001664 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001665 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001666 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001667 else if (!strcmp(args[0], "redirect")) {
1668 int pol = ACL_COND_NONE;
1669 struct acl_cond *cond;
1670 struct redirect_rule *rule;
1671 int cur_arg;
1672 int type = REDIRECT_TYPE_NONE;
1673 int code = 302;
1674 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001675 char *cookie = NULL;
1676 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001677 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001678
1679 cur_arg = 1;
1680 while (*(args[cur_arg])) {
1681 if (!strcmp(args[cur_arg], "location")) {
1682 if (!*args[cur_arg + 1]) {
1683 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1684 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001687 }
1688
1689 type = REDIRECT_TYPE_LOCATION;
1690 cur_arg++;
1691 destination = args[cur_arg];
1692 }
1693 else if (!strcmp(args[cur_arg], "prefix")) {
1694 if (!*args[cur_arg + 1]) {
1695 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1696 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001699 }
1700
1701 type = REDIRECT_TYPE_PREFIX;
1702 cur_arg++;
1703 destination = args[cur_arg];
1704 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001705 else if (!strcmp(args[cur_arg], "set-cookie")) {
1706 if (!*args[cur_arg + 1]) {
1707 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1708 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001711 }
1712
1713 cur_arg++;
1714 cookie = args[cur_arg];
1715 cookie_set = 1;
1716 }
1717 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1718 if (!*args[cur_arg + 1]) {
1719 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1720 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001723 }
1724
1725 cur_arg++;
1726 cookie = args[cur_arg];
1727 cookie_set = 0;
1728 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001729 else if (!strcmp(args[cur_arg],"code")) {
1730 if (!*args[cur_arg + 1]) {
1731 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1732 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001735 }
1736 cur_arg++;
1737 code = atol(args[cur_arg]);
1738 if (code < 301 || code > 303) {
1739 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1740 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001743 }
1744 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001745 else if (!strcmp(args[cur_arg],"drop-query")) {
1746 flags |= REDIRECT_FLAG_DROP_QS;
1747 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001748 else if (!strcmp(args[cur_arg], "if")) {
1749 pol = ACL_COND_IF;
1750 cur_arg++;
1751 break;
1752 }
1753 else if (!strcmp(args[cur_arg], "unless")) {
1754 pol = ACL_COND_UNLESS;
1755 cur_arg++;
1756 break;
1757 }
1758 else {
1759 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1760 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001763 }
1764 cur_arg++;
1765 }
1766
1767 if (type == REDIRECT_TYPE_NONE) {
1768 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1769 file, linenum, args[0]);
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
1774 if (pol == ACL_COND_NONE) {
1775 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1776 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001777 err_code |= ERR_ALERT | ERR_FATAL;
1778 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001779 }
1780
1781 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001782 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001783 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001786 }
1787
Willy Tarreaua9802632008-07-25 19:13:19 +02001788 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001789 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001790 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1791 rule->cond = cond;
1792 rule->rdr_str = strdup(destination);
1793 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001794 if (cookie) {
1795 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1796 * a clear consists in appending "; Max-Age=0" at the end.
1797 */
1798 rule->cookie_len = strlen(cookie);
1799 if (cookie_set)
1800 rule->cookie_str = strdup(cookie);
1801 else {
1802 rule->cookie_str = malloc(rule->cookie_len + 12);
1803 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1804 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1805 rule->cookie_len += 11;
1806 }
1807 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001808 rule->type = type;
1809 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001810 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001811 LIST_INIT(&rule->list);
1812 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001813 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001814 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001815 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001816 int pol = ACL_COND_NONE;
1817 struct acl_cond *cond;
1818 struct switching_rule *rule;
1819
Willy Tarreaub099aca2008-10-12 17:26:37 +02001820 if (curproxy == &defproxy) {
1821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001824 }
1825
Willy Tarreau55ea7572007-06-17 19:56:27 +02001826 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001827 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001828
1829 if (*(args[1]) == 0) {
1830 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001831 err_code |= ERR_ALERT | ERR_FATAL;
1832 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001833 }
1834
1835 if (!strcmp(args[2], "if"))
1836 pol = ACL_COND_IF;
1837 else if (!strcmp(args[2], "unless"))
1838 pol = ACL_COND_UNLESS;
1839
1840 if (pol == ACL_COND_NONE) {
1841 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1842 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001845 }
1846
1847 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001848 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001849 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001850 err_code |= ERR_ALERT | ERR_FATAL;
1851 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001852 }
1853
Willy Tarreaua9802632008-07-25 19:13:19 +02001854 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001855 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001856 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001857 struct acl *acl;
1858 const char *name;
1859
1860 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1861 name = acl ? acl->name : "(unknown)";
1862 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1863 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001864 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001865 }
1866
Willy Tarreau55ea7572007-06-17 19:56:27 +02001867 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1868 rule->cond = cond;
1869 rule->be.name = strdup(args[1]);
1870 LIST_INIT(&rule->list);
1871 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001874 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001876
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1878 curproxy->uri_auth = NULL; /* we must detach from the default config */
1879
1880 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001881 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 +02001882 err_code |= ERR_ALERT | ERR_FATAL;
1883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 } else if (!strcmp(args[1], "uri")) {
1885 if (*(args[2]) == 0) {
1886 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1890 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001891 err_code |= ERR_ALERT | ERR_ABORT;
1892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 }
1894 } else if (!strcmp(args[1], "realm")) {
1895 if (*(args[2]) == 0) {
1896 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1900 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001901 err_code |= ERR_ALERT | ERR_ABORT;
1902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001904 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001905 unsigned interval;
1906
1907 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1908 if (err) {
1909 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1910 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001913 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1914 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_ALERT | ERR_ABORT;
1916 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 } else if (!strcmp(args[1], "auth")) {
1919 if (*(args[2]) == 0) {
1920 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1924 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001925 err_code |= ERR_ALERT | ERR_ABORT;
1926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 }
1928 } else if (!strcmp(args[1], "scope")) {
1929 if (*(args[2]) == 0) {
1930 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1934 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_ABORT;
1936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
1938 } else if (!strcmp(args[1], "enable")) {
1939 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1940 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_ABORT;
1942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001944 } else if (!strcmp(args[1], "hide-version")) {
1945 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1946 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_ABORT;
1948 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001949 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001950 } else if (!strcmp(args[1], "show-node")) {
1951
1952 if (*args[2]) {
1953 int i;
1954 char c;
1955
1956 for (i=0; args[2][i]; i++) {
1957 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02001958 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001959 break;
1960 }
1961
1962 if (!i || args[2][i]) {
1963 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1964 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1965 file, linenum, args[0], args[1]);
1966 err_code |= ERR_ALERT | ERR_FATAL;
1967 goto out;
1968 }
1969 }
1970
1971 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1972 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1973 err_code |= ERR_ALERT | ERR_ABORT;
1974 goto out;
1975 }
1976 } else if (!strcmp(args[1], "show-desc")) {
1977 char *desc = NULL;
1978
1979 if (*args[2]) {
1980 int i, len=0;
1981 char *d;
1982
1983 for(i=2; *args[i]; i++)
1984 len += strlen(args[i])+1;
1985
1986 desc = d = (char *)calloc(1, len);
1987
1988 d += sprintf(d, "%s", args[2]);
1989 for(i=3; *args[i]; i++)
1990 d += sprintf(d, " %s", args[i]);
1991 }
1992
1993 if (!*args[2] && !global.desc)
1994 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
1995 file, linenum, args[1]);
1996 else {
1997 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
1998 free(desc);
1999 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2000 err_code |= ERR_ALERT | ERR_ABORT;
2001 goto out;
2002 }
2003 free(desc);
2004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002006 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010 }
2011 }
2012 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002013 int optnum;
2014
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002015 if (*(args[1]) == '\0') {
2016 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2017 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002021
2022 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2023 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002024 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2025 err_code |= ERR_WARN;
2026 goto out;
2027 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002028
Willy Tarreau3842f002009-06-14 11:39:52 +02002029 curproxy->no_options &= ~cfg_opts[optnum].val;
2030 curproxy->options &= ~cfg_opts[optnum].val;
2031
2032 switch (kwm) {
2033 case KWM_STD:
2034 curproxy->options |= cfg_opts[optnum].val;
2035 break;
2036 case KWM_NO:
2037 curproxy->no_options |= cfg_opts[optnum].val;
2038 break;
2039 case KWM_DEF: /* already cleared */
2040 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002041 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002042
Willy Tarreau93893792009-07-23 13:19:11 +02002043 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002044 }
2045 }
2046
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002047 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2048 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002049 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2050 err_code |= ERR_WARN;
2051 goto out;
2052 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002053
Willy Tarreau3842f002009-06-14 11:39:52 +02002054 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2055 curproxy->options2 &= ~cfg_opts2[optnum].val;
2056
2057 switch (kwm) {
2058 case KWM_STD:
2059 curproxy->options2 |= cfg_opts2[optnum].val;
2060 break;
2061 case KWM_NO:
2062 curproxy->no_options2 |= cfg_opts2[optnum].val;
2063 break;
2064 case KWM_DEF: /* already cleared */
2065 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002066 }
Willy Tarreau93893792009-07-23 13:19:11 +02002067 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002068 }
2069 }
2070
Willy Tarreau3842f002009-06-14 11:39:52 +02002071 if (kwm != KWM_STD) {
2072 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002073 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002076 }
2077
Emeric Brun3a058f32009-06-30 18:26:00 +02002078 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002080 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002082 if (*(args[2]) != '\0') {
2083 if (!strcmp(args[2], "clf")) {
2084 curproxy->options2 |= PR_O2_CLFLOG;
2085 } else {
2086 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002087 err_code |= ERR_ALERT | ERR_FATAL;
2088 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002089 }
2090 }
2091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 else if (!strcmp(args[1], "tcplog"))
2093 /* generate a detailed TCP log */
2094 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 else if (!strcmp(args[1], "tcpka")) {
2096 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002097 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002099
2100 if (curproxy->cap & PR_CAP_FE)
2101 curproxy->options |= PR_O_TCP_CLI_KA;
2102 if (curproxy->cap & PR_CAP_BE)
2103 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
2105 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002106 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_WARN;
2108
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002110 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002111 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002112 curproxy->options &= ~PR_O_SMTP_CHK;
2113 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 if (!*args[2]) { /* no argument */
2115 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2116 curproxy->check_len = strlen(DEF_CHECK_REQ);
2117 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002118 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 curproxy->check_req = (char *)malloc(reqlen);
2120 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2121 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2122 } else { /* more arguments : METHOD URI [HTTP_VER] */
2123 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2124 if (*args[4])
2125 reqlen += strlen(args[4]);
2126 else
2127 reqlen += strlen("HTTP/1.0");
2128
2129 curproxy->check_req = (char *)malloc(reqlen);
2130 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2131 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2132 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002133 }
2134 else if (!strcmp(args[1], "ssl-hello-chk")) {
2135 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002138
Willy Tarreaua534fea2008-08-03 12:19:50 +02002139 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002140 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002141 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002142 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 }
Willy Tarreau23677902007-05-08 23:50:35 +02002144 else if (!strcmp(args[1], "smtpchk")) {
2145 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002146 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002147 curproxy->options &= ~PR_O_HTTP_CHK;
2148 curproxy->options &= ~PR_O_SSL3_CHK;
2149 curproxy->options |= PR_O_SMTP_CHK;
2150
2151 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2152 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2153 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2154 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2155 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2156 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2157 curproxy->check_req = (char *)malloc(reqlen);
2158 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2159 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2160 } else {
2161 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2162 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2163 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2164 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2165 }
2166 }
2167 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002168 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002169 int cur_arg;
2170
2171 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2172 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002173 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002174
2175 curproxy->options |= PR_O_FWDFOR;
2176
2177 free(curproxy->fwdfor_hdr_name);
2178 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2179 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2180
2181 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2182 cur_arg = 2;
2183 while (*(args[cur_arg])) {
2184 if (!strcmp(args[cur_arg], "except")) {
2185 /* suboption except - needs additional argument for it */
2186 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2187 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2188 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002191 }
2192 /* flush useless bits */
2193 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002194 cur_arg += 2;
2195 } else if (!strcmp(args[cur_arg], "header")) {
2196 /* suboption header - needs additional argument for it */
2197 if (*(args[cur_arg+1]) == 0) {
2198 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> 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;
Ross Westaf72a1d2008-08-03 10:51:45 +02002202 }
2203 free(curproxy->fwdfor_hdr_name);
2204 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2205 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2206 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002207 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002208 /* unknown suboption - catchall */
2209 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2210 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002213 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002214 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002215 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002216 else if (!strcmp(args[1], "originalto")) {
2217 int cur_arg;
2218
2219 /* insert x-original-to field, but not for the IP address listed as an except.
2220 * set default options (ie: bitfield, header name, etc)
2221 */
2222
2223 curproxy->options |= PR_O_ORGTO;
2224
2225 free(curproxy->orgto_hdr_name);
2226 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2227 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2228
2229 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2230 cur_arg = 2;
2231 while (*(args[cur_arg])) {
2232 if (!strcmp(args[cur_arg], "except")) {
2233 /* suboption except - needs additional argument for it */
2234 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2235 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2236 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002239 }
2240 /* flush useless bits */
2241 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2242 cur_arg += 2;
2243 } else if (!strcmp(args[cur_arg], "header")) {
2244 /* suboption header - needs additional argument for it */
2245 if (*(args[cur_arg+1]) == 0) {
2246 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> 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 free(curproxy->orgto_hdr_name);
2252 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2253 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2254 cur_arg += 2;
2255 } else {
2256 /* unknown suboption - catchall */
2257 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2258 file, linenum, args[0], args[1]);
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 } /* end while loop */
2263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 else {
2265 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 }
Willy Tarreau93893792009-07-23 13:19:11 +02002269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002271 else if (!strcmp(args[0], "default_backend")) {
2272 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002274
2275 if (*(args[1]) == 0) {
2276 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002279 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002280 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002281 curproxy->defbe.name = strdup(args[1]);
2282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002286
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002287 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 /* enable reconnections to dispatch */
2291 curproxy->options |= PR_O_REDISP;
2292 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002293 else if (!strcmp(args[0], "http-check")) {
2294 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002296
2297 if (strcmp(args[1], "disable-on-404") == 0) {
2298 /* enable a graceful server shutdown on an HTTP 404 response */
2299 curproxy->options |= PR_O_DISABLE404;
2300 }
2301 else {
2302 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002305 }
2306 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002307 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002308 if (curproxy == &defproxy) {
2309 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002312 }
2313
Willy Tarreaub80c2302007-11-30 20:51:32 +01002314 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002316
2317 if (strcmp(args[1], "fail") == 0) {
2318 /* add a condition to fail monitor requests */
2319 int pol = ACL_COND_NONE;
2320 struct acl_cond *cond;
2321
2322 if (!strcmp(args[2], "if"))
2323 pol = ACL_COND_IF;
2324 else if (!strcmp(args[2], "unless"))
2325 pol = ACL_COND_UNLESS;
2326
2327 if (pol == ACL_COND_NONE) {
2328 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2329 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002332 }
2333
2334 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2335 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2336 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002339 }
Willy Tarreaua9802632008-07-25 19:13:19 +02002340 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002341 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002342 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2343 }
2344 else {
2345 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002348 }
2349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350#ifdef TPROXY
2351 else if (!strcmp(args[0], "transparent")) {
2352 /* enable transparent proxy connections */
2353 curproxy->options |= PR_O_TRANSP;
2354 }
2355#endif
2356 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 if (*(args[1]) == 0) {
2361 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
2365 curproxy->maxconn = atol(args[1]);
2366 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002367 else if (!strcmp(args[0], "backlog")) { /* backlog */
2368 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002370
2371 if (*(args[1]) == 0) {
2372 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002375 }
2376 curproxy->backlog = atol(args[1]);
2377 }
Willy Tarreau86034312006-12-29 00:10:33 +01002378 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002381
Willy Tarreau86034312006-12-29 00:10:33 +01002382 if (*(args[1]) == 0) {
2383 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002386 }
2387 curproxy->fullconn = atol(args[1]);
2388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2390 if (*(args[1]) == 0) {
2391 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002395 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2396 if (err) {
2397 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2398 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002401 }
2402 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
2404 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2405 if (curproxy == &defproxy) {
2406 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002410 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002412
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 if (strchr(args[1], ':') == NULL) {
2414 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 }
2418 curproxy->dispatch_addr = *str2sa(args[1]);
2419 }
2420 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002421 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002424 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002425 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2426 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431 else if (!strcmp(args[0], "server")) { /* server address */
2432 int cur_arg;
2433 char *rport;
2434 char *raddr;
2435 short realport;
2436 int do_check;
2437
2438 if (curproxy == &defproxy) {
2439 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002443 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445
2446 if (!*args[2]) {
2447 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2448 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002452
2453 err = invalid_char(args[1]);
2454 if (err) {
2455 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2456 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002459 }
2460
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2462 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002463 err_code |= ERR_ALERT | ERR_ABORT;
2464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 }
2466
2467 /* the servers are linked backwards first */
2468 newsrv->next = curproxy->srv;
2469 curproxy->srv = newsrv;
2470 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002471 newsrv->puid = curproxy->next_svid++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002472 newsrv->conf.file = file;
2473 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474
2475 LIST_INIT(&newsrv->pendconns);
2476 do_check = 0;
2477 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002478 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 newsrv->id = strdup(args[1]);
2480
2481 /* several ways to check the port component :
2482 * - IP => port=+0, relative
2483 * - IP: => port=+0, relative
2484 * - IP:N => port=N, absolute
2485 * - IP:+N => port=+N, relative
2486 * - IP:-N => port=-N, relative
2487 */
2488 raddr = strdup(args[2]);
2489 rport = strchr(raddr, ':');
2490 if (rport) {
2491 *rport++ = 0;
2492 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002493 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 newsrv->state |= SRV_MAPPORTS;
2495 } else {
2496 realport = 0;
2497 newsrv->state |= SRV_MAPPORTS;
2498 }
2499
2500 newsrv->addr = *str2sa(raddr);
2501 newsrv->addr.sin_port = htons(realport);
2502 free(raddr);
2503
2504 newsrv->curfd = -1; /* no health-check in progress */
2505 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002506 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2507 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 newsrv->rise = DEF_RISETIME;
2509 newsrv->fall = DEF_FALLTIME;
2510 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002511 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002512 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002513 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002514
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 cur_arg = 3;
2516 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002517 if (!strcmp(args[cur_arg], "id")) {
2518 struct server *target;
2519
2520 if (!*args[cur_arg + 1]) {
2521 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2522 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002525 }
2526
2527 newsrv->puid = atol(args[cur_arg + 1]);
2528
2529 if (newsrv->puid< 1001) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002530 Alert("parsing [%s:%d]: custom id has to be > 1000.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002531 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002534 }
2535
2536 for (target = proxy->srv; target; target = target->next)
2537 if (newsrv != target && newsrv->puid == target->puid) {
2538 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2539 file, linenum, newsrv->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002542 }
2543 cur_arg += 2;
2544 }
2545 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 newsrv->cookie = strdup(args[cur_arg + 1]);
2547 newsrv->cklen = strlen(args[cur_arg + 1]);
2548 cur_arg += 2;
2549 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002550 else if (!strcmp(args[cur_arg], "redir")) {
2551 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2552 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2553 cur_arg += 2;
2554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002556 if (!*args[cur_arg + 1]) {
2557 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2558 file, linenum, args[cur_arg]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002564 if (newsrv->rise <= 0) {
2565 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2566 file, linenum, args[cur_arg]);
2567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
2569 }
2570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 newsrv->health = newsrv->rise;
2572 cur_arg += 2;
2573 }
2574 else if (!strcmp(args[cur_arg], "fall")) {
2575 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002576
2577 if (!*args[cur_arg + 1]) {
2578 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2579 file, linenum, args[cur_arg]);
2580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
2582 }
2583
2584 if (newsrv->fall <= 0) {
2585 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2586 file, linenum, args[cur_arg]);
2587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
2589 }
2590
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 cur_arg += 2;
2592 }
2593 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002594 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2595 if (err) {
2596 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2597 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002600 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002601 if (val <= 0) {
2602 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2603 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002606 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002607 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 cur_arg += 2;
2609 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002610 else if (!strcmp(args[cur_arg], "fastinter")) {
2611 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2612 if (err) {
2613 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2614 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002617 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002618 if (val <= 0) {
2619 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2620 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002623 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002624 newsrv->fastinter = val;
2625 cur_arg += 2;
2626 }
2627 else if (!strcmp(args[cur_arg], "downinter")) {
2628 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2629 if (err) {
2630 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2631 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002634 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002635 if (val <= 0) {
2636 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2637 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002640 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002641 newsrv->downinter = val;
2642 cur_arg += 2;
2643 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002644 else if (!strcmp(args[cur_arg], "addr")) {
2645 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002646 cur_arg += 2;
2647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 else if (!strcmp(args[cur_arg], "port")) {
2649 newsrv->check_port = atol(args[cur_arg + 1]);
2650 cur_arg += 2;
2651 }
2652 else if (!strcmp(args[cur_arg], "backup")) {
2653 newsrv->state |= SRV_BACKUP;
2654 cur_arg ++;
2655 }
2656 else if (!strcmp(args[cur_arg], "weight")) {
2657 int w;
2658 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002659 if (w < 0 || w > 256) {
2660 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002664 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002665 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 cur_arg += 2;
2667 }
2668 else if (!strcmp(args[cur_arg], "minconn")) {
2669 newsrv->minconn = atol(args[cur_arg + 1]);
2670 cur_arg += 2;
2671 }
2672 else if (!strcmp(args[cur_arg], "maxconn")) {
2673 newsrv->maxconn = atol(args[cur_arg + 1]);
2674 cur_arg += 2;
2675 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002676 else if (!strcmp(args[cur_arg], "maxqueue")) {
2677 newsrv->maxqueue = atol(args[cur_arg + 1]);
2678 cur_arg += 2;
2679 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002680 else if (!strcmp(args[cur_arg], "slowstart")) {
2681 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002682 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002683 if (err) {
2684 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2685 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002688 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002689 if (val <= 0) {
2690 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2691 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002694 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002695 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002696 cur_arg += 2;
2697 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002698 else if (!strcmp(args[cur_arg], "track")) {
2699
2700 if (!*args[cur_arg + 1]) {
2701 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2702 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002705 }
2706
2707 newsrv->trackit = strdup(args[cur_arg + 1]);
2708
2709 cur_arg += 2;
2710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 else if (!strcmp(args[cur_arg], "check")) {
2712 global.maxsock++;
2713 do_check = 1;
2714 cur_arg += 1;
2715 }
2716 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002717 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002719#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002720 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002721 file, linenum, "source", "usesrc");
2722#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002723 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002725#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 }
2729 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002730 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2731
2732 if (port_low != port_high) {
2733 int i;
2734 if (port_low <= 0 || port_low > 65535 ||
2735 port_high <= 0 || port_high > 65535 ||
2736 port_low > port_high) {
2737 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2738 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002741 }
2742 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2743 for (i = 0; i < newsrv->sport_range->size; i++)
2744 newsrv->sport_range->ports[i] = port_low + i;
2745 }
2746
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002748 while (*(args[cur_arg])) {
2749 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002750#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2751#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002752 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2753 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2754 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002757 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002758#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002759 if (!*args[cur_arg + 1]) {
2760 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2761 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002764 }
2765 if (!strcmp(args[cur_arg + 1], "client")) {
2766 newsrv->state |= SRV_TPROXY_CLI;
2767 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2768 newsrv->state |= SRV_TPROXY_CIP;
2769 } else {
2770 newsrv->state |= SRV_TPROXY_ADDR;
2771 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2772 }
2773 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002774#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002775 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002776#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002777 cur_arg += 2;
2778 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002779#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002780 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002781 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002784#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2785 } /* "usesrc" */
2786
2787 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2788#ifdef SO_BINDTODEVICE
2789 if (!*args[cur_arg + 1]) {
2790 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2791 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002794 }
2795 if (newsrv->iface_name)
2796 free(newsrv->iface_name);
2797
2798 newsrv->iface_name = strdup(args[cur_arg + 1]);
2799 newsrv->iface_len = strlen(newsrv->iface_name);
2800 global.last_checks |= LSTCHK_NETADM;
2801#else
2802 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2803 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002806#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002807 cur_arg += 2;
2808 continue;
2809 }
2810 /* this keyword in not an option of "source" */
2811 break;
2812 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002814 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2815 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2816 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002821 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 +02002822 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 }
2826 }
2827
2828 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002829 if (newsrv->trackit) {
2830 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2831 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002834 }
2835
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002836 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2837 newsrv->check_port = newsrv->check_addr.sin_port;
2838
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2840 newsrv->check_port = realport; /* by default */
2841 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002842 /* not yet valid, because no port was set on
2843 * the server either. We'll check if we have
2844 * a known port on the first listener.
2845 */
2846 struct listener *l;
2847 l = curproxy->listen;
2848 if (l) {
2849 int port;
2850 port = (l->addr.ss_family == AF_INET6)
2851 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2852 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2853 newsrv->check_port = port;
2854 }
2855 }
2856 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2858 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02002862
2863 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 newsrv->state |= SRV_CHECKED;
2865 }
2866
2867 if (newsrv->state & SRV_BACKUP)
2868 curproxy->srv_bck++;
2869 else
2870 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002871
2872 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 }
2874 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002875 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 int facility;
2877
2878 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2879 curproxy->logfac1 = global.logfac1;
2880 curproxy->logsrv1 = global.logsrv1;
2881 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002882 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 curproxy->logfac2 = global.logfac2;
2884 curproxy->logsrv2 = global.logsrv2;
2885 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002886 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
2888 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002889 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890
2891 facility = get_log_facility(args[2]);
2892 if (facility < 0) {
2893 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2894 exit(1);
2895 }
2896
2897 level = 7; /* max syslog level = debug */
2898 if (*(args[3])) {
2899 level = get_log_level(args[3]);
2900 if (level < 0) {
2901 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2902 exit(1);
2903 }
2904 }
2905
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002906 minlvl = 0; /* limit syslog level to this level (emerg) */
2907 if (*(args[4])) {
2908 minlvl = get_log_level(args[4]);
2909 if (level < 0) {
2910 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2911 exit(1);
2912 }
2913 }
2914
Robert Tsai81ae1952007-12-05 10:47:29 +01002915 if (args[1][0] == '/') {
2916 logsrv.u.addr.sa_family = AF_UNIX;
2917 logsrv.u.un = *str2sun(args[1]);
2918 } else {
2919 logsrv.u.addr.sa_family = AF_INET;
2920 logsrv.u.in = *str2sa(args[1]);
2921 if (!logsrv.u.in.sin_port) {
2922 logsrv.u.in.sin_port =
2923 htons(SYSLOG_PORT);
2924 }
2925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926
2927 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002928 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929 curproxy->logfac1 = facility;
2930 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002931 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 }
2933 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002934 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 curproxy->logfac2 = facility;
2936 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002937 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 }
2939 else {
2940 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 }
2944 }
2945 else {
2946 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2947 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 }
2951 }
2952 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002953 int cur_arg;
2954
Willy Tarreau977b8e42006-12-29 14:19:17 +01002955 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002956 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002957
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002959 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2960 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02002961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002963 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002964
2965 /* we must first clear any optional default setting */
2966 curproxy->options &= ~PR_O_TPXY_MASK;
2967 free(curproxy->iface_name);
2968 curproxy->iface_name = NULL;
2969 curproxy->iface_len = 0;
2970
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 curproxy->source_addr = *str2sa(args[1]);
2972 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002973
2974 cur_arg = 2;
2975 while (*(args[cur_arg])) {
2976 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002977#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2978#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002979 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2980 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2981 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002984 }
2985#endif
2986 if (!*args[cur_arg + 1]) {
2987 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2988 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002991 }
2992
2993 if (!strcmp(args[cur_arg + 1], "client")) {
2994 curproxy->options |= PR_O_TPXY_CLI;
2995 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2996 curproxy->options |= PR_O_TPXY_CIP;
2997 } else {
2998 curproxy->options |= PR_O_TPXY_ADDR;
2999 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3000 }
3001 global.last_checks |= LSTCHK_NETADM;
3002#if !defined(CONFIG_HAP_LINUX_TPROXY)
3003 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003004#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003005#else /* no TPROXY support */
3006 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003007 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003010#endif
3011 cur_arg += 2;
3012 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003013 }
3014
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003015 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3016#ifdef SO_BINDTODEVICE
3017 if (!*args[cur_arg + 1]) {
3018 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003022 }
3023 if (curproxy->iface_name)
3024 free(curproxy->iface_name);
3025
3026 curproxy->iface_name = strdup(args[cur_arg + 1]);
3027 curproxy->iface_len = strlen(curproxy->iface_name);
3028 global.last_checks |= LSTCHK_NETADM;
3029#else
3030 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3031 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003034#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003035 cur_arg += 2;
3036 continue;
3037 }
3038 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3039 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003044 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3045 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3046 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3051 regex_t *preg;
3052 if (curproxy == &defproxy) {
3053 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003059
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 if (*(args[1]) == 0 || *(args[2]) == 0) {
3061 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 }
3066
3067 preg = calloc(1, sizeof(regex_t));
3068 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3069 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 }
3073
3074 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3075 if (err) {
3076 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3077 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003080 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 }
3082 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3083 regex_t *preg;
3084 if (curproxy == &defproxy) {
3085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003089 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003091
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 if (*(args[1]) == 0) {
3093 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 }
3097
3098 preg = calloc(1, sizeof(regex_t));
3099 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3100 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
3104
3105 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003106 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 }
3108 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3109 regex_t *preg;
3110 if (curproxy == &defproxy) {
3111 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003115 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003117
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 if (*(args[1]) == 0) {
3119 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 }
3123
3124 preg = calloc(1, sizeof(regex_t));
3125 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3126 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 }
3130
3131 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003132 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 }
3134 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3135 regex_t *preg;
3136 if (curproxy == &defproxy) {
3137 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003141 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003143
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 if (*(args[1]) == 0) {
3145 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
3149
3150 preg = calloc(1, sizeof(regex_t));
3151 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3152 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
3156
3157 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003158 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 }
3160 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3161 regex_t *preg;
3162 if (curproxy == &defproxy) {
3163 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003167 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003169
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 if (*(args[1]) == 0) {
3171 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 }
3175
3176 preg = calloc(1, sizeof(regex_t));
3177 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3178 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 }
3182
3183 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003184 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003186 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3187 regex_t *preg;
3188 if (curproxy == &defproxy) {
3189 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003192 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003193 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003195
Willy Tarreaub8750a82006-09-03 09:56:00 +02003196 if (*(args[1]) == 0) {
3197 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003200 }
3201
3202 preg = calloc(1, sizeof(regex_t));
3203 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3204 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003207 }
3208
3209 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003210 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003211 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003212 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3213 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003214 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003215 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003218 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003219 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003221
Willy Tarreau977b8e42006-12-29 14:19:17 +01003222 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003223 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3224 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003227 }
3228
3229 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003230 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003231 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003234 }
3235
3236 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003237 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003238 }
3239 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3240 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003241 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003242 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003245 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003246 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003248
Willy Tarreau977b8e42006-12-29 14:19:17 +01003249 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003250 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3251 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003254 }
3255
3256 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003257 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003258 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003261 }
3262
3263 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003264 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3267 regex_t *preg;
3268 if (curproxy == &defproxy) {
3269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003273 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003275
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 if (*(args[1]) == 0 || *(args[2]) == 0) {
3277 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
3282
3283 preg = calloc(1, sizeof(regex_t));
3284 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3285 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
3289
3290 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3291 if (err) {
3292 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3293 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003297 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
3299 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3300 regex_t *preg;
3301 if (curproxy == &defproxy) {
3302 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003306 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003308
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 if (*(args[1]) == 0) {
3310 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 }
3314
3315 preg = calloc(1, sizeof(regex_t));
3316 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3317 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
3321
3322 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003323 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 }
3325 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3326 regex_t *preg;
3327 if (curproxy == &defproxy) {
3328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003332 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003334
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 if (*(args[1]) == 0) {
3336 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 }
3340
3341 preg = calloc(1, sizeof(regex_t));
3342 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3343 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 }
3347
3348 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003349 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 }
3351 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3352 regex_t *preg;
3353 if (curproxy == &defproxy) {
3354 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003358 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003360
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 if (*(args[1]) == 0) {
3362 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 }
3366
3367 preg = calloc(1, sizeof(regex_t));
3368 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3369 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
3373
3374 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003375 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 }
3377 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3378 regex_t *preg;
3379 if (curproxy == &defproxy) {
3380 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003384 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003386
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 if (*(args[1]) == 0) {
3388 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 }
3392
3393 preg = calloc(1, sizeof(regex_t));
3394 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3395 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 }
3399
3400 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003401 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003403 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3404 regex_t *preg;
3405 if (curproxy == &defproxy) {
3406 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003409 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003410 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003411 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003412
Willy Tarreaub8750a82006-09-03 09:56:00 +02003413 if (*(args[1]) == 0) {
3414 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003417 }
3418
3419 preg = calloc(1, sizeof(regex_t));
3420 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3421 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003424 }
3425
3426 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003427 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3430 if (curproxy == &defproxy) {
3431 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003435 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437
3438 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3439 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
3443
3444 if (*(args[1]) == 0) {
3445 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 }
3449
3450 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003451 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 }
3453 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3454 regex_t *preg;
3455
3456 if (*(args[1]) == 0 || *(args[2]) == 0) {
3457 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003462 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003464
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 preg = calloc(1, sizeof(regex_t));
3466 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3467 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 }
3471
3472 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3473 if (err) {
3474 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3475 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003476 err_code |= ERR_ALERT | ERR_FATAL;
3477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003479 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 }
3481 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3482 regex_t *preg;
3483 if (curproxy == &defproxy) {
3484 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003488 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003490
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 if (*(args[1]) == 0) {
3492 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 }
3496
3497 preg = calloc(1, sizeof(regex_t));
3498 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3499 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 }
3503
3504 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3505 if (err) {
3506 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3507 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
3511 }
3512 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3513 regex_t *preg;
3514 if (curproxy == &defproxy) {
3515 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003519 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003521
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 if (*(args[1]) == 0) {
3523 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 }
3527
3528 preg = calloc(1, sizeof(regex_t));
3529 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3530 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 }
3534
3535 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3536 if (err) {
3537 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3538 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 }
3542 }
3543 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3544 regex_t *preg;
3545 if (curproxy == &defproxy) {
3546 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003550 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552
3553 if (*(args[1]) == 0 || *(args[2]) == 0) {
3554 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
3559
3560 preg = calloc(1, sizeof(regex_t));
3561 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3562 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
3566
3567 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3568 if (err) {
3569 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3570 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 }
3574 }
3575 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3576 regex_t *preg;
3577 if (curproxy == &defproxy) {
3578 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003582 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003584
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 if (*(args[1]) == 0) {
3586 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 }
3590
3591 preg = calloc(1, sizeof(regex_t));
3592 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3593 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 }
3597
3598 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3599 if (err) {
3600 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3601 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 }
3605 }
3606 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3607 regex_t *preg;
3608 if (curproxy == &defproxy) {
3609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003615
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 if (*(args[1]) == 0) {
3617 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003620 }
3621
3622 preg = calloc(1, sizeof(regex_t));
3623 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3624 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 }
3628
3629 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3630 if (err) {
3631 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3632 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 }
3636 }
3637 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3638 if (curproxy == &defproxy) {
3639 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003643 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645
3646 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3647 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
3651
3652 if (*(args[1]) == 0) {
3653 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 }
3657
3658 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3659 }
3660 else if (!strcmp(args[0], "errorloc") ||
3661 !strcmp(args[0], "errorloc302") ||
3662 !strcmp(args[0], "errorloc303")) { /* error location */
3663 int errnum, errlen;
3664 char *err;
3665
Willy Tarreau977b8e42006-12-29 14:19:17 +01003666 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003667 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003668
Willy Tarreaubaaee002006-06-26 02:48:02 +02003669 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003670 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 }
3674
3675 errnum = atol(args[1]);
3676 if (!strcmp(args[0], "errorloc303")) {
3677 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3678 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3679 } else {
3680 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3681 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3682 }
3683
Willy Tarreau0f772532006-12-23 20:51:41 +01003684 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3685 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003686 chunk_destroy(&curproxy->errmsg[rc]);
3687 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003688 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003691
3692 if (rc >= HTTP_ERR_SIZE) {
3693 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3694 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 free(err);
3696 }
3697 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003698 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3699 int errnum, errlen, fd;
3700 char *err;
3701 struct stat stat;
3702
3703 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003705
3706 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003707 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003710 }
3711
3712 fd = open(args[2], O_RDONLY);
3713 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3714 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3715 file, linenum, args[2], args[1]);
3716 if (fd >= 0)
3717 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003720 }
3721
Willy Tarreau27a674e2009-08-17 07:23:33 +02003722 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003723 errlen = stat.st_size;
3724 } else {
3725 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003726 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003728 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003729 }
3730
3731 err = malloc(errlen); /* malloc() must succeed during parsing */
3732 errnum = read(fd, err, errlen);
3733 if (errnum != errlen) {
3734 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3735 file, linenum, args[2], args[1]);
3736 close(fd);
3737 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003740 }
3741 close(fd);
3742
3743 errnum = atol(args[1]);
3744 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3745 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003746 chunk_destroy(&curproxy->errmsg[rc]);
3747 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003748 break;
3749 }
3750 }
3751
3752 if (rc >= HTTP_ERR_SIZE) {
3753 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3754 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003756 free(err);
3757 }
3758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003760 struct cfg_kw_list *kwl;
3761 int index;
3762
3763 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3764 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3765 if (kwl->kw[index].section != CFG_LISTEN)
3766 continue;
3767 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3768 /* prepare error message just in case */
3769 snprintf(trash, sizeof(trash),
3770 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003771 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3772 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003773 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003776 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003777 else if (rc > 0) {
3778 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_WARN;
3780 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003781 }
Willy Tarreau93893792009-07-23 13:19:11 +02003782 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003783 }
3784 }
3785 }
3786
Willy Tarreau6daf3432008-01-22 16:44:08 +01003787 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
Willy Tarreau93893792009-07-23 13:19:11 +02003791 out:
3792 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793}
3794
3795
3796/*
3797 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003798 * Returns the error code, 0 if OK, or any combination of :
3799 * - ERR_ABORT: must abort ASAP
3800 * - ERR_FATAL: we can continue parsing but not start the service
3801 * - ERR_WARN: a warning has been emitted
3802 * - ERR_ALERT: an alert has been emitted
3803 * Only the two first ones can stop processing, the two others are just
3804 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003806int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003808 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 FILE *f;
3810 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003812 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 if ((f=fopen(file,"r")) == NULL)
3815 return -1;
3816
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003817 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003818 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003819 char *end;
3820 char *args[MAX_LINE_ARGS + 1];
3821 char *line = thisline;
3822
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 linenum++;
3824
3825 end = line + strlen(line);
3826
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003827 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3828 /* Check if we reached the limit and the last char is not \n.
3829 * Watch out for the last line without the terminating '\n'!
3830 */
3831 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003832 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003834 }
3835
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003837 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 line++;
3839
3840 arg = 0;
3841 args[arg] = line;
3842
3843 while (*line && arg < MAX_LINE_ARGS) {
3844 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3845 * C equivalent value. Other combinations left unchanged (eg: \1).
3846 */
3847 if (*line == '\\') {
3848 int skip = 0;
3849 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3850 *line = line[1];
3851 skip = 1;
3852 }
3853 else if (line[1] == 'r') {
3854 *line = '\r';
3855 skip = 1;
3856 }
3857 else if (line[1] == 'n') {
3858 *line = '\n';
3859 skip = 1;
3860 }
3861 else if (line[1] == 't') {
3862 *line = '\t';
3863 skip = 1;
3864 }
3865 else if (line[1] == 'x') {
3866 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3867 unsigned char hex1, hex2;
3868 hex1 = toupper(line[2]) - '0';
3869 hex2 = toupper(line[3]) - '0';
3870 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3871 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3872 *line = (hex1<<4) + hex2;
3873 skip = 3;
3874 }
3875 else {
3876 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 }
3879 }
3880 if (skip) {
3881 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3882 end -= skip;
3883 }
3884 line++;
3885 }
3886 else if (*line == '#' || *line == '\n' || *line == '\r') {
3887 /* end of string, end of loop */
3888 *line = 0;
3889 break;
3890 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003891 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003893 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003894 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895 line++;
3896 args[++arg] = line;
3897 }
3898 else {
3899 line++;
3900 }
3901 }
3902
3903 /* empty line */
3904 if (!**args)
3905 continue;
3906
Willy Tarreau540abe42007-05-02 20:50:16 +02003907 /* zero out remaining args and ensure that at least one entry
3908 * is zeroed out.
3909 */
3910 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 args[arg] = line;
3912 }
3913
Willy Tarreau3842f002009-06-14 11:39:52 +02003914 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003915 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003916 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003917 for (arg=0; *args[arg+1]; arg++)
3918 args[arg] = args[arg+1]; // shift args after inversion
3919 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003920 else if (!strcmp(args[0], "default")) {
3921 kwm = KWM_DEF;
3922 for (arg=0; *args[arg+1]; arg++)
3923 args[arg] = args[arg+1]; // shift args after inversion
3924 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003925
Willy Tarreau3842f002009-06-14 11:39:52 +02003926 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3927 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003929 }
3930
Willy Tarreau977b8e42006-12-29 14:19:17 +01003931 if (!strcmp(args[0], "listen") ||
3932 !strcmp(args[0], "frontend") ||
3933 !strcmp(args[0], "backend") ||
3934 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003935 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003937 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003938 cursection = strdup(args[0]);
3939 }
3940 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003942 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003943 cursection = strdup(args[0]);
3944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 /* else it's a section keyword */
3946
3947 switch (confsect) {
3948 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 break;
3951 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003952 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 break;
3954 default:
3955 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003958
3959 if (err_code & ERR_ABORT)
3960 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003962 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003963 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003965 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003966}
3967
Willy Tarreaubb925012009-07-23 13:36:36 +02003968/*
3969 * Returns the error code, 0 if OK, or any combination of :
3970 * - ERR_ABORT: must abort ASAP
3971 * - ERR_FATAL: we can continue parsing but not start the service
3972 * - ERR_WARN: a warning has been emitted
3973 * - ERR_ALERT: an alert has been emitted
3974 * Only the two first ones can stop processing, the two others are just
3975 * indicators.
3976 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003977int check_config_validity()
3978{
3979 int cfgerr = 0;
3980 struct proxy *curproxy = NULL;
3981 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003982 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983
3984 /*
3985 * Now, check for the integrity of all that we have collected.
3986 */
3987
3988 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003989 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003991 /* first, we will invert the proxy list order */
3992 curproxy = NULL;
3993 while (proxy) {
3994 struct proxy *next;
3995
3996 next = proxy->next;
3997 proxy->next = curproxy;
3998 curproxy = proxy;
3999 if (!next)
4000 break;
4001 proxy = next;
4002 }
4003
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004005 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008 }
4009
4010 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004011 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004012 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004013
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004015 /* ensure we don't keep listeners uselessly bound */
4016 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 curproxy = curproxy->next;
4018 continue;
4019 }
4020
Willy Tarreauff01a212009-03-15 13:46:16 +01004021 switch (curproxy->mode) {
4022 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004023 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004024 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004025 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4026 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004027 cfgerr++;
4028 }
4029
4030 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004031 Warning("config : servers will be ignored for %s '%s'.\n",
4032 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004033 break;
4034
4035 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004036 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004037 break;
4038
4039 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004040 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004041 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004042 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4043 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004044 cfgerr++;
4045 }
4046 break;
4047 }
4048
4049 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004050 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4051 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 cfgerr++;
4053 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004054
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004055 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004056 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004057 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004058 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4059 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004060 cfgerr++;
4061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004063 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004064 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4065 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004066 cfgerr++;
4067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004069 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004070 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4071 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004072 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004073 }
4074 }
4075 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4076 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4077 /* If no LB algo is set in a backend, and we're not in
4078 * transparent mode, dispatch mode nor proxy mode, we
4079 * want to use balance roundrobin by default.
4080 */
4081 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4082 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083 }
4084 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004085
Willy Tarreau82936582007-11-30 15:20:09 +01004086 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4087 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004088 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4089 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004090 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004091 }
4092
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004093 /* if a default backend was specified, let's find it */
4094 if (curproxy->defbe.name) {
4095 struct proxy *target;
4096
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004097 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
4098 if (!target) {
4099 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4100 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004101 cfgerr++;
4102 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004103 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4104 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004105 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004106 } else {
4107 free(curproxy->defbe.name);
4108 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004109 /* we force the backend to be present on at least all of
4110 * the frontend's processes.
4111 */
4112 target->bind_proc = curproxy->bind_proc ?
4113 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 }
4115 }
4116
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004117 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004118 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4119 /* map jump target for ACT_SETBE in req_rep chain */
4120 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004121 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004122 struct proxy *target;
4123
Willy Tarreaua496b602006-12-17 23:15:24 +01004124 if (exp->action != ACT_SETBE)
4125 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004126
4127 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
4128 if (!target) {
4129 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4130 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004131 cfgerr++;
4132 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004133 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4134 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004135 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004136 } else {
4137 free((void *)exp->replace);
4138 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004139 /* we force the backend to be present on at least all of
4140 * the frontend's processes.
4141 */
4142 target->bind_proc = curproxy->bind_proc ?
4143 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004144 }
4145 }
4146 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004147
4148 /* find the target proxy for 'use_backend' rules */
4149 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004150 struct proxy *target;
4151
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004152 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004153
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004154 if (!target) {
4155 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4156 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004157 cfgerr++;
4158 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004159 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4160 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004161 cfgerr++;
4162 } else {
4163 free((void *)rule->be.name);
4164 rule->be.backend = 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 Tarreau55ea7572007-06-17 19:56:27 +02004170 }
4171 }
4172
Willy Tarreau2738a142006-07-08 17:28:09 +02004173 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004174 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004175 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004176 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004177 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004178 " | While not properly invalid, you will certainly encounter various problems\n"
4179 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004180 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004181 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004182 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004183 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004184
Willy Tarreau1fa31262007-12-03 00:36:16 +01004185 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4186 * We must still support older configurations, so let's find out whether those
4187 * parameters have been set or must be copied from contimeouts.
4188 */
4189 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004190 if (!curproxy->timeout.tarpit ||
4191 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004192 /* tarpit timeout not set. We search in the following order:
4193 * default.tarpit, curr.connect, default.connect.
4194 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004195 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004196 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004197 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004198 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004199 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004200 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004201 }
4202 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004203 (!curproxy->timeout.queue ||
4204 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004205 /* queue timeout not set. We search in the following order:
4206 * default.queue, curr.connect, default.connect.
4207 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004208 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004209 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004210 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004211 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004212 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004213 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004214 }
4215 }
4216
Willy Tarreauf3c69202006-07-09 16:42:34 +02004217 if (curproxy->options & PR_O_SSL3_CHK) {
4218 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4219 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4220 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4221 }
4222
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004223 /* The small pools required for the capture lists */
4224 if (curproxy->nb_req_cap)
4225 curproxy->req_cap_pool = create_pool("ptrcap",
4226 curproxy->nb_req_cap * sizeof(char *),
4227 MEM_F_SHARED);
4228 if (curproxy->nb_rsp_cap)
4229 curproxy->rsp_cap_pool = create_pool("ptrcap",
4230 curproxy->nb_rsp_cap * sizeof(char *),
4231 MEM_F_SHARED);
4232
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004233 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4234 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4235 MEM_F_SHARED);
4236
Willy Tarreau86034312006-12-29 00:10:33 +01004237 /* for backwards compatibility with "listen" instances, if
4238 * fullconn is not set but maxconn is set, then maxconn
4239 * is used.
4240 */
4241 if (!curproxy->fullconn)
4242 curproxy->fullconn = curproxy->maxconn;
4243
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 /* first, we will invert the servers list order */
4245 newsrv = NULL;
4246 while (curproxy->srv) {
4247 struct server *next;
4248
4249 next = curproxy->srv->next;
4250 curproxy->srv->next = newsrv;
4251 newsrv = curproxy->srv;
4252 if (!next)
4253 break;
4254 curproxy->srv = next;
4255 }
4256
Willy Tarreau20697042007-11-15 23:26:18 +01004257 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004258 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004260 /* We have to initialize the server lookup mechanism depending
4261 * on what LB algorithm was choosen.
4262 */
4263
4264 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4265 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4266 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004267 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4268 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4269 init_server_map(curproxy);
4270 } else {
4271 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4272 fwrr_init_server_groups(curproxy);
4273 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004274 break;
4275 case BE_LB_KIND_LC:
4276 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004277 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004278 break;
4279 case BE_LB_KIND_HI:
4280 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
Willy Tarreaub625a082007-11-26 01:15:43 +01004281 init_server_map(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004282 break;
4283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284
4285 if (curproxy->options & PR_O_LOGASAP)
4286 curproxy->to_log &= ~LW_BYTES;
4287
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004288 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4289 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4290 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4291 proxy_type_str(curproxy), curproxy->id);
4292 err_code |= ERR_WARN;
4293 }
4294
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004296 * ensure that we're not cross-dressing a TCP server into HTTP.
4297 */
4298 newsrv = curproxy->srv;
4299 while (newsrv != NULL) {
4300 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004301 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4302 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004303 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004304 }
4305 newsrv = newsrv->next;
4306 }
4307
4308 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 * If this server supports a maxconn parameter, it needs a dedicated
4310 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004311 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 */
4313 newsrv = curproxy->srv;
4314 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004315 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 /* Only 'minconn' was specified, or it was higher than or equal
4317 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4318 * this will avoid further useless expensive computations.
4319 */
4320 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004321 } else if (newsrv->maxconn && !newsrv->minconn) {
4322 /* minconn was not specified, so we set it to maxconn */
4323 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004324 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004325 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4326 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004327 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 }
4329
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004330 if (newsrv->trackit) {
4331 struct proxy *px;
4332 struct server *srv;
4333 char *pname, *sname;
4334
4335 pname = newsrv->trackit;
4336 sname = strrchr(pname, '/');
4337
4338 if (sname)
4339 *sname++ = '\0';
4340 else {
4341 sname = pname;
4342 pname = NULL;
4343 }
4344
4345 if (pname) {
4346 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4347 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004348 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4349 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004350 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004351 cfgerr++;
4352 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004353 }
4354 } else
4355 px = curproxy;
4356
4357 srv = findserver(px, sname);
4358 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004359 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4360 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004361 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004362 cfgerr++;
4363 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004364 }
4365
4366 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004367 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004368 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004369 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004370 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004371 cfgerr++;
4372 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004373 }
4374
4375 if (curproxy != px &&
4376 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004377 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004378 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004379 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004380 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004381 cfgerr++;
4382 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004383 }
4384
4385 newsrv->tracked = srv;
4386 newsrv->tracknext = srv->tracknext;
4387 srv->tracknext = newsrv;
4388
4389 free(newsrv->trackit);
4390 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004391 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 newsrv = newsrv->next;
4393 }
4394
Willy Tarreauc1a21672009-08-16 22:37:44 +02004395 if (curproxy->cap & PR_CAP_FE) {
4396 if (curproxy->tcp_req.inspect_delay ||
4397 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4398 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4399
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004400 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004401 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004402 curproxy->fe_rsp_ana |= AN_RTR_HTTP_HDR;
4403 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004404
4405 /* both TCP and HTTP must check switching rules */
4406 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4407 }
4408
4409 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004410 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004411 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004412 curproxy->be_rsp_ana |= AN_RTR_HTTP_HDR;
4413 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004414
4415 /* If the backend does requires RDP cookie persistence, we have to
4416 * enable the corresponding analyser.
4417 */
4418 if (curproxy->options2 & PR_O2_RDPC_PRST)
4419 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4420 }
4421
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004422 listener = NULL;
4423 while (curproxy->listen) {
4424 struct listener *next;
4425
4426 next = curproxy->listen->next;
4427 curproxy->listen->next = listener;
4428 listener = curproxy->listen;
4429
4430 if (!next)
4431 break;
4432
4433 curproxy->listen = next;
4434 }
4435
Willy Tarreaue6b98942007-10-29 01:09:36 +01004436 /* adjust this proxy's listeners */
4437 listener = curproxy->listen;
4438 while (listener) {
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004439 /* enable separate counters */
4440 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4441 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4442 if (!listener->name) {
4443 sprintf(trash, "sock-%d", listener->luid);
4444 listener->name = strdup(trash);
4445 }
4446 }
4447
Willy Tarreaue6b98942007-10-29 01:09:36 +01004448 if (curproxy->options & PR_O_TCP_NOLING)
4449 listener->options |= LI_O_NOLINGER;
4450 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004451 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004452 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004453 listener->accept = event_accept;
4454 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004455 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004456 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004457
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004458 /* smart accept mode is automatic in HTTP mode */
4459 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4460 (curproxy->mode == PR_MODE_HTTP &&
4461 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4462 listener->options |= LI_O_NOQUICKACK;
4463
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004464 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004465 listener = listener->next;
4466 }
4467
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 curproxy = curproxy->next;
4469 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004470
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004471 /*
4472 * Recount currently required checks.
4473 */
4474
4475 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4476 int optnum;
4477
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004478 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4479 if (curproxy->options & cfg_opts[optnum].val)
4480 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004481
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004482 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4483 if (curproxy->options2 & cfg_opts2[optnum].val)
4484 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004485 }
4486
Willy Tarreaubb925012009-07-23 13:36:36 +02004487 if (cfgerr > 0)
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 out:
4490 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491}
4492
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004493/*
4494 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4495 * parsing sessions.
4496 */
4497void cfg_register_keywords(struct cfg_kw_list *kwl)
4498{
4499 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4500}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004502/*
4503 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4504 */
4505void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4506{
4507 LIST_DEL(&kwl->list);
4508 LIST_INIT(&kwl->list);
4509}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510
4511/*
4512 * Local variables:
4513 * c-indent-level: 8
4514 * c-basic-offset: 8
4515 * End:
4516 */