blob: 8e582a6278cfd17021815c91c8621ef3de4760cc [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 Tarreau092549f2009-10-04 21:11:42 +0200865 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
866 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
867 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200868 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200869 }
870 }
871
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
873 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200874 err_code |= ERR_ALERT | ERR_ABORT;
875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100877
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 curproxy->next = proxy;
879 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200880 curproxy->conf.file = file;
881 curproxy->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200883 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200884 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200885 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100886 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200887 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200888 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889
Willy Tarreauee991362007-05-14 14:37:50 +0200890 /* Timeouts are defined as -1, so we cannot use the zeroed area
891 * as a default value.
892 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100893 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200894
895 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100897 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898
899 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100900 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200901 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200902 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200903 err_code |= ERR_FATAL;
904 goto out;
905 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200906 new = curproxy->listen;
907 while (new != last) {
908 new->conf.file = file;
909 new->conf.line = linenum;
910 new = new->next;
911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 global.maxsock++;
913 }
914
915 /* set default values */
916 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100918 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200919 curproxy->no_options = defproxy.no_options;
920 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100921 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100922 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200923 curproxy->except_net = defproxy.except_net;
924 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200925 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200926 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200928 if (defproxy.fwdfor_hdr_len) {
929 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
930 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
931 }
932
Willy Tarreau977b8e42006-12-29 14:19:17 +0100933 if (curproxy->cap & PR_CAP_FE) {
934 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100935 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200936 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100937
938 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200939 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
940 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100941
942 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944
Willy Tarreau977b8e42006-12-29 14:19:17 +0100945 if (curproxy->cap & PR_CAP_BE) {
946 curproxy->fullconn = defproxy.fullconn;
947 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948
Willy Tarreau977b8e42006-12-29 14:19:17 +0100949 if (defproxy.check_req)
950 curproxy->check_req = strdup(defproxy.check_req);
951 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952
Willy Tarreau977b8e42006-12-29 14:19:17 +0100953 if (defproxy.cookie_name)
954 curproxy->cookie_name = strdup(defproxy.cookie_name);
955 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100956
Emeric Brun647caf12009-06-30 17:57:00 +0200957 if (defproxy.rdp_cookie_name)
958 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
959 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
960
Willy Tarreau01732802007-11-01 22:48:15 +0100961 if (defproxy.url_param_name)
962 curproxy->url_param_name = strdup(defproxy.url_param_name);
963 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100964
Benoitaffb4812009-03-25 13:02:10 +0100965 if (defproxy.hh_name)
966 curproxy->hh_name = strdup(defproxy.hh_name);
967 curproxy->hh_len = defproxy.hh_len;
968 curproxy->hh_match_domain = defproxy.hh_match_domain;
969
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100970 if (defproxy.iface_name)
971 curproxy->iface_name = strdup(defproxy.iface_name);
972 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200975 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100976 if (defproxy.capture_name)
977 curproxy->capture_name = strdup(defproxy.capture_name);
978 curproxy->capture_namelen = defproxy.capture_namelen;
979 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981
Willy Tarreau977b8e42006-12-29 14:19:17 +0100982 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100983 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100984 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100985 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100986 curproxy->uri_auth = defproxy.uri_auth;
987 curproxy->mon_net = defproxy.mon_net;
988 curproxy->mon_mask = defproxy.mon_mask;
989 if (defproxy.monitor_uri)
990 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
991 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100992 if (defproxy.defbe.name)
993 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100994 }
995
996 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100997 curproxy->timeout.connect = defproxy.timeout.connect;
998 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100999 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001000 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001001 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001002 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001003 curproxy->source_addr = defproxy.source_addr;
1004 }
1005
Willy Tarreaubaaee002006-06-26 02:48:02 +02001006 curproxy->mode = defproxy.mode;
1007 curproxy->logfac1 = defproxy.logfac1;
1008 curproxy->logsrv1 = defproxy.logsrv1;
1009 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001010 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 curproxy->logfac2 = defproxy.logfac2;
1012 curproxy->logsrv2 = defproxy.logsrv2;
1013 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001014 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001016 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
1017 curproxy->next_svid = 1; /* server id 0 is reserved */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001018 curproxy->next_lid = 1; /* listener id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +02001019
Willy Tarreau93893792009-07-23 13:19:11 +02001020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1023 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001024 /* FIXME-20070101: we should do this too at the end of the
1025 * config parsing to free all default values.
1026 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001027 free(defproxy.check_req);
1028 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001029 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001030 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001031 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001032 free(defproxy.capture_name);
1033 free(defproxy.monitor_uri);
1034 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001035 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001036 free(defproxy.fwdfor_hdr_name);
1037 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001038
Willy Tarreaua534fea2008-08-03 12:19:50 +02001039 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001040 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001041
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 /* we cannot free uri_auth because it might already be used */
1043 init_default_instance();
1044 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001045 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 }
1048 else if (curproxy == NULL) {
1049 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
1053
Willy Tarreau977b8e42006-12-29 14:19:17 +01001054
1055 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001057 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001058 int cur_arg;
1059
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 if (curproxy == &defproxy) {
1061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001065 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001066 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067
1068 if (strchr(args[1], ':') == NULL) {
1069 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001074
1075 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001076 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
1079 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001080
Willy Tarreau90a570f2009-10-04 20:54:54 +02001081 new_listen = curproxy->listen;
1082 while (new_listen != last_listen) {
1083 new_listen->conf.file = file;
1084 new_listen->conf.line = linenum;
1085 new_listen = new_listen->next;
1086 }
1087
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001088 cur_arg = 2;
1089 while (*(args[cur_arg])) {
1090 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1091#ifdef SO_BINDTODEVICE
1092 struct listener *l;
1093
1094 if (!*args[cur_arg + 1]) {
1095 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1096 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001099 }
1100
1101 for (l = curproxy->listen; l != last_listen; l = l->next)
1102 l->interface = strdup(args[cur_arg + 1]);
1103
1104 global.last_checks |= LSTCHK_NETADM;
1105
1106 cur_arg += 2;
1107 continue;
1108#else
1109 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1110 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001113#endif
1114 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001115 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1116#ifdef TCP_MAXSEG
1117 struct listener *l;
1118 int mss;
1119
1120 if (!*args[cur_arg + 1]) {
1121 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1122 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001125 }
1126
1127 mss = str2uic(args[cur_arg + 1]);
1128 if (mss < 1 || mss > 65535) {
1129 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001133 }
1134
1135 for (l = curproxy->listen; l != last_listen; l = l->next)
1136 l->maxseg = mss;
1137
1138 cur_arg += 2;
1139 continue;
1140#else
1141 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1142 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001143 err_code |= ERR_ALERT | ERR_FATAL;
1144 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001145#endif
1146 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001147 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001148#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001149 struct listener *l;
1150
1151 for (l = curproxy->listen; l != last_listen; l = l->next)
1152 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001153
1154 cur_arg ++;
1155 continue;
1156#else
1157 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1158 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001161#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001162 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001163
1164 if (!strcmp(args[cur_arg], "name")) {
1165 struct listener *l;
1166
1167 for (l = curproxy->listen; l != last_listen; l = l->next)
1168 l->name = strdup(args[cur_arg + 1]);
1169
1170 cur_arg += 2;
1171 continue;
1172 }
1173
1174 if (!strcmp(args[cur_arg], "id")) {
1175 struct listener *l;
1176
1177 if (curproxy->listen->next != last_listen) {
1178 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1179 file, linenum, args[cur_arg]);
1180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto out;
1182 }
1183
1184 if (!*args[cur_arg + 1]) {
1185 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1186 file, linenum, args[cur_arg]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190
1191 curproxy->listen->luid = atol(args[cur_arg + 1]);
1192
1193 if (curproxy->listen->luid < 1001) {
1194 Alert("parsing [%s:%d]: custom id has to be > 1000\n",
1195 file, linenum);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
1198 }
1199
Willy Tarreau9d7e3352009-10-04 21:13:39 +02001200 for (l = curproxy->listen; l; l = l->next)
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001201 if (curproxy->listen != l && l->luid == curproxy->listen->luid) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001202 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1203 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
1206 }
1207 cur_arg += 2;
1208 continue;
1209 }
1210
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001211 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001212 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001216 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001218 }
1219 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1220 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1221 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1222 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001223 err_code |= ERR_ALERT | ERR_FATAL;
1224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001225 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001226 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001227 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001228
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 /* flush useless bits */
1230 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001233 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001234 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001235 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001236
Willy Tarreau1c47f852006-07-09 08:22:27 +02001237 if (!*args[1]) {
1238 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1239 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001242 }
1243
Willy Tarreaua534fea2008-08-03 12:19:50 +02001244 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001245 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001246 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001247 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001248 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1249
Willy Tarreau93893792009-07-23 13:19:11 +02001250 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1253 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1254 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1255 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1256 else {
1257 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 }
1261 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001262 else if (!strcmp(args[0], "id")) {
1263 struct proxy *target;
1264
1265 if (curproxy == &defproxy) {
1266 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1267 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001270 }
1271
1272 if (!*args[1]) {
1273 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1274 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001277 }
1278
1279 curproxy->uuid = atol(args[1]);
1280
1281 if (curproxy->uuid < 1001) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02001282 Alert("parsing [%s:%d]: custom id has to be > 1000.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001283 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001286 }
1287
1288 for (target = proxy; target; target = target->next)
1289 if (curproxy != target && curproxy->uuid == target->uuid) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001290 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1291 file, linenum, proxy_type_str(curproxy), curproxy->id,
1292 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001295 }
1296 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001297 else if (!strcmp(args[0], "description")) {
1298 int i, len=0;
1299 char *d;
1300
1301 if (!*args[1]) {
1302 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1303 file, linenum, args[0]);
1304 return -1;
1305 }
1306
1307 for(i=1; *args[i]; i++)
1308 len += strlen(args[i])+1;
1309
1310 d = (char *)calloc(1, len);
1311 curproxy->desc = d;
1312
1313 d += sprintf(d, "%s", args[1]);
1314 for(i=2; *args[i]; i++)
1315 d += sprintf(d, " %s", args[i]);
1316
1317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1319 curproxy->state = PR_STSTOPPED;
1320 }
1321 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1322 curproxy->state = PR_STNEW;
1323 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001324 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1325 int cur_arg = 1;
1326 unsigned int set = 0;
1327
1328 while (*args[cur_arg]) {
1329 int u;
1330 if (strcmp(args[cur_arg], "all") == 0) {
1331 set = 0;
1332 break;
1333 }
1334 else if (strcmp(args[cur_arg], "odd") == 0) {
1335 set |= 0x55555555;
1336 }
1337 else if (strcmp(args[cur_arg], "even") == 0) {
1338 set |= 0xAAAAAAAA;
1339 }
1340 else {
1341 u = str2uic(args[cur_arg]);
1342 if (u < 1 || u > 32) {
1343 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001347 }
1348 if (u > global.nbproc) {
1349 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1350 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001352 }
1353 set |= 1 << (u - 1);
1354 }
1355 cur_arg++;
1356 }
1357 curproxy->bind_proc = set;
1358 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001359 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001360 if (curproxy == &defproxy) {
1361 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001364 }
1365
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001366 err = invalid_char(args[1]);
1367 if (err) {
1368 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1369 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001370 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001371 }
1372
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001373 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1374 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1375 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001378 }
1379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1381 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382
Willy Tarreau977b8e42006-12-29 14:19:17 +01001383 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001384 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001385
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 if (*(args[1]) == 0) {
1387 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1388 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001389 err_code |= ERR_ALERT | ERR_FATAL;
1390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001392
1393 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 curproxy->cookie_name = strdup(args[1]);
1395 curproxy->cookie_len = strlen(curproxy->cookie_name);
1396
1397 cur_arg = 2;
1398 while (*(args[cur_arg])) {
1399 if (!strcmp(args[cur_arg], "rewrite")) {
1400 curproxy->options |= PR_O_COOK_RW;
1401 }
1402 else if (!strcmp(args[cur_arg], "indirect")) {
1403 curproxy->options |= PR_O_COOK_IND;
1404 }
1405 else if (!strcmp(args[cur_arg], "insert")) {
1406 curproxy->options |= PR_O_COOK_INS;
1407 }
1408 else if (!strcmp(args[cur_arg], "nocache")) {
1409 curproxy->options |= PR_O_COOK_NOC;
1410 }
1411 else if (!strcmp(args[cur_arg], "postonly")) {
1412 curproxy->options |= PR_O_COOK_POST;
1413 }
1414 else if (!strcmp(args[cur_arg], "prefix")) {
1415 curproxy->options |= PR_O_COOK_PFX;
1416 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001417 else if (!strcmp(args[cur_arg], "domain")) {
1418 if (!*args[cur_arg + 1]) {
1419 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1420 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001423 }
1424
1425 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1426 /* rfc2109, 4.3.2 Rejecting Cookies */
1427 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1428 " dots or does not start with a dot.\n",
1429 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001432 }
1433
1434 err = invalid_domainchar(args[cur_arg + 1]);
1435 if (err) {
1436 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1437 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001438 err_code |= ERR_ALERT | ERR_FATAL;
1439 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001440 }
1441
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001442 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001443 cur_arg++;
1444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001446 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 }
1451 cur_arg++;
1452 }
1453 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1454 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1455 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001456 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 }
1458
1459 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1460 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1461 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 }
1464 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001465 else if (!strcmp(args[0], "persist")) { /* persist */
1466 if (*(args[1]) == 0) {
1467 Alert("parsing [%s:%d] : missing persist method.\n",
1468 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001469 err_code |= ERR_ALERT | ERR_FATAL;
1470 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001471 }
1472
1473 if (!strncmp(args[1], "rdp-cookie", 10)) {
1474 curproxy->options2 |= PR_O2_RDPC_PRST;
1475
1476 if (*(args[1] + 10 ) == '(') { /* cookie name */
1477 const char *beg, *end;
1478
1479 beg = args[1] + 11;
1480 end = strchr(beg, ')');
1481
1482 if (!end || end == beg) {
1483 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1484 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001485 err_code |= ERR_ALERT | ERR_FATAL;
1486 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001487 }
1488
1489 free(curproxy->rdp_cookie_name);
1490 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1491 curproxy->rdp_cookie_len = end-beg;
1492 }
1493 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1494 free(curproxy->rdp_cookie_name);
1495 curproxy->rdp_cookie_name = strdup("msts");
1496 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1497 }
1498 else { /* syntax */
1499 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1500 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001501 err_code |= ERR_ALERT | ERR_FATAL;
1502 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001503 }
1504 }
1505 else {
1506 Alert("parsing [%s:%d] : unknown persist method.\n",
1507 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001510 }
1511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001515 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001516
Willy Tarreaubaaee002006-06-26 02:48:02 +02001517 if (*(args[5]) == 0) {
1518 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522 }
1523 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001524 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001525 curproxy->appsession_name = strdup(args[1]);
1526 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1527 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001528 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1529 if (err) {
1530 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1531 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001534 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001535 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001536
Willy Tarreau51041c72007-09-09 21:56:53 +02001537 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1538 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001539 err_code |= ERR_ALERT | ERR_ABORT;
1540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 }
1542 } /* Url App Session */
1543 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001544 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001545 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001546
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548 if (*(args[4]) == 0) {
1549 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001554 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 curproxy->capture_name = strdup(args[2]);
1556 curproxy->capture_namelen = strlen(curproxy->capture_name);
1557 curproxy->capture_len = atol(args[4]);
1558 if (curproxy->capture_len >= CAPTURE_LEN) {
1559 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1560 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001561 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 curproxy->capture_len = CAPTURE_LEN - 1;
1563 }
1564 curproxy->to_log |= LW_COOKIE;
1565 }
1566 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1567 struct cap_hdr *hdr;
1568
1569 if (curproxy == &defproxy) {
1570 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 +02001571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 }
1574
1575 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1576 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1577 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001578 err_code |= ERR_ALERT | ERR_FATAL;
1579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 }
1581
1582 hdr = calloc(sizeof(struct cap_hdr), 1);
1583 hdr->next = curproxy->req_cap;
1584 hdr->name = strdup(args[3]);
1585 hdr->namelen = strlen(args[3]);
1586 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001587 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 hdr->index = curproxy->nb_req_cap++;
1589 curproxy->req_cap = hdr;
1590 curproxy->to_log |= LW_REQHDR;
1591 }
1592 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1593 struct cap_hdr *hdr;
1594
1595 if (curproxy == &defproxy) {
1596 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 +02001597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 }
1600
1601 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1602 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1603 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
1605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001606 }
1607 hdr = calloc(sizeof(struct cap_hdr), 1);
1608 hdr->next = curproxy->rsp_cap;
1609 hdr->name = strdup(args[3]);
1610 hdr->namelen = strlen(args[3]);
1611 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001612 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 hdr->index = curproxy->nb_rsp_cap++;
1614 curproxy->rsp_cap = hdr;
1615 curproxy->to_log |= LW_RSPHDR;
1616 }
1617 else {
1618 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
1623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001626 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001627
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 if (*(args[1]) == 0) {
1629 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 }
1634 curproxy->conn_retries = atol(args[1]);
1635 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001636 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1637 int pol = ACL_COND_NONE;
1638 struct acl_cond *cond;
1639
Willy Tarreaub099aca2008-10-12 17:26:37 +02001640 if (curproxy == &defproxy) {
1641 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001644 }
1645
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001646 if (!strcmp(args[1], "if"))
1647 pol = ACL_COND_IF;
1648 else if (!strcmp(args[1], "unless"))
1649 pol = ACL_COND_UNLESS;
1650
1651 if (pol == ACL_COND_NONE) {
1652 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
1655 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001656 }
1657
1658 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1659 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1660 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
1662 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001663 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001664 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001665 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001666 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001667 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001668 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001669 else if (!strcmp(args[0], "redirect")) {
1670 int pol = ACL_COND_NONE;
1671 struct acl_cond *cond;
1672 struct redirect_rule *rule;
1673 int cur_arg;
1674 int type = REDIRECT_TYPE_NONE;
1675 int code = 302;
1676 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001677 char *cookie = NULL;
1678 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001679 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001680
1681 cur_arg = 1;
1682 while (*(args[cur_arg])) {
1683 if (!strcmp(args[cur_arg], "location")) {
1684 if (!*args[cur_arg + 1]) {
1685 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1686 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001689 }
1690
1691 type = REDIRECT_TYPE_LOCATION;
1692 cur_arg++;
1693 destination = args[cur_arg];
1694 }
1695 else if (!strcmp(args[cur_arg], "prefix")) {
1696 if (!*args[cur_arg + 1]) {
1697 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1698 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001701 }
1702
1703 type = REDIRECT_TYPE_PREFIX;
1704 cur_arg++;
1705 destination = args[cur_arg];
1706 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001707 else if (!strcmp(args[cur_arg], "set-cookie")) {
1708 if (!*args[cur_arg + 1]) {
1709 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1710 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001713 }
1714
1715 cur_arg++;
1716 cookie = args[cur_arg];
1717 cookie_set = 1;
1718 }
1719 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1720 if (!*args[cur_arg + 1]) {
1721 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1722 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001725 }
1726
1727 cur_arg++;
1728 cookie = args[cur_arg];
1729 cookie_set = 0;
1730 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001731 else if (!strcmp(args[cur_arg],"code")) {
1732 if (!*args[cur_arg + 1]) {
1733 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1734 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001737 }
1738 cur_arg++;
1739 code = atol(args[cur_arg]);
1740 if (code < 301 || code > 303) {
1741 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1742 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001745 }
1746 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001747 else if (!strcmp(args[cur_arg],"drop-query")) {
1748 flags |= REDIRECT_FLAG_DROP_QS;
1749 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001750 else if (!strcmp(args[cur_arg], "if")) {
1751 pol = ACL_COND_IF;
1752 cur_arg++;
1753 break;
1754 }
1755 else if (!strcmp(args[cur_arg], "unless")) {
1756 pol = ACL_COND_UNLESS;
1757 cur_arg++;
1758 break;
1759 }
1760 else {
1761 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1762 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001765 }
1766 cur_arg++;
1767 }
1768
1769 if (type == REDIRECT_TYPE_NONE) {
1770 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1771 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001774 }
1775
1776 if (pol == ACL_COND_NONE) {
1777 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001781 }
1782
1783 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001784 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001785 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001788 }
1789
Willy Tarreaua9802632008-07-25 19:13:19 +02001790 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001791 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001792 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1793 rule->cond = cond;
1794 rule->rdr_str = strdup(destination);
1795 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001796 if (cookie) {
1797 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1798 * a clear consists in appending "; Max-Age=0" at the end.
1799 */
1800 rule->cookie_len = strlen(cookie);
1801 if (cookie_set)
1802 rule->cookie_str = strdup(cookie);
1803 else {
1804 rule->cookie_str = malloc(rule->cookie_len + 12);
1805 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1806 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1807 rule->cookie_len += 11;
1808 }
1809 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001810 rule->type = type;
1811 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001812 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001813 LIST_INIT(&rule->list);
1814 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001815 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001816 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001817 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001818 int pol = ACL_COND_NONE;
1819 struct acl_cond *cond;
1820 struct switching_rule *rule;
1821
Willy Tarreaub099aca2008-10-12 17:26:37 +02001822 if (curproxy == &defproxy) {
1823 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001826 }
1827
Willy Tarreau55ea7572007-06-17 19:56:27 +02001828 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001829 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001830
1831 if (*(args[1]) == 0) {
1832 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001835 }
1836
1837 if (!strcmp(args[2], "if"))
1838 pol = ACL_COND_IF;
1839 else if (!strcmp(args[2], "unless"))
1840 pol = ACL_COND_UNLESS;
1841
1842 if (pol == ACL_COND_NONE) {
1843 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1844 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001847 }
1848
1849 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001850 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001851 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001854 }
1855
Willy Tarreaua9802632008-07-25 19:13:19 +02001856 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001857 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001858 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001859 struct acl *acl;
1860 const char *name;
1861
1862 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1863 name = acl ? acl->name : "(unknown)";
1864 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1865 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001867 }
1868
Willy Tarreau55ea7572007-06-17 19:56:27 +02001869 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1870 rule->cond = cond;
1871 rule->be.name = strdup(args[1]);
1872 LIST_INIT(&rule->list);
1873 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1874 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001877 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001878
Willy Tarreaubaaee002006-06-26 02:48:02 +02001879 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1880 curproxy->uri_auth = NULL; /* we must detach from the default config */
1881
1882 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001883 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 +02001884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 } else if (!strcmp(args[1], "uri")) {
1887 if (*(args[2]) == 0) {
1888 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1892 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001893 err_code |= ERR_ALERT | ERR_ABORT;
1894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 }
1896 } else if (!strcmp(args[1], "realm")) {
1897 if (*(args[2]) == 0) {
1898 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1902 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001903 err_code |= ERR_ALERT | ERR_ABORT;
1904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001906 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001907 unsigned interval;
1908
1909 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1910 if (err) {
1911 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1912 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001915 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1916 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001917 err_code |= ERR_ALERT | ERR_ABORT;
1918 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 } else if (!strcmp(args[1], "auth")) {
1921 if (*(args[2]) == 0) {
1922 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001923 err_code |= ERR_ALERT | ERR_FATAL;
1924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1926 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001927 err_code |= ERR_ALERT | ERR_ABORT;
1928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 }
1930 } else if (!strcmp(args[1], "scope")) {
1931 if (*(args[2]) == 0) {
1932 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1936 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_ALERT | ERR_ABORT;
1938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 }
1940 } else if (!strcmp(args[1], "enable")) {
1941 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1942 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_ALERT | ERR_ABORT;
1944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001946 } else if (!strcmp(args[1], "hide-version")) {
1947 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1948 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_ALERT | ERR_ABORT;
1950 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001951 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001952 } else if (!strcmp(args[1], "show-node")) {
1953
1954 if (*args[2]) {
1955 int i;
1956 char c;
1957
1958 for (i=0; args[2][i]; i++) {
1959 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02001960 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001961 break;
1962 }
1963
1964 if (!i || args[2][i]) {
1965 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1966 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1967 file, linenum, args[0], args[1]);
1968 err_code |= ERR_ALERT | ERR_FATAL;
1969 goto out;
1970 }
1971 }
1972
1973 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1974 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1975 err_code |= ERR_ALERT | ERR_ABORT;
1976 goto out;
1977 }
1978 } else if (!strcmp(args[1], "show-desc")) {
1979 char *desc = NULL;
1980
1981 if (*args[2]) {
1982 int i, len=0;
1983 char *d;
1984
1985 for(i=2; *args[i]; i++)
1986 len += strlen(args[i])+1;
1987
1988 desc = d = (char *)calloc(1, len);
1989
1990 d += sprintf(d, "%s", args[2]);
1991 for(i=3; *args[i]; i++)
1992 d += sprintf(d, " %s", args[i]);
1993 }
1994
1995 if (!*args[2] && !global.desc)
1996 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
1997 file, linenum, args[1]);
1998 else {
1999 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2000 free(desc);
2001 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2002 err_code |= ERR_ALERT | ERR_ABORT;
2003 goto out;
2004 }
2005 free(desc);
2006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002008 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 }
2013 }
2014 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002015 int optnum;
2016
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002017 if (*(args[1]) == '\0') {
2018 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002023
2024 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2025 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002026 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2027 err_code |= ERR_WARN;
2028 goto out;
2029 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002030
Willy Tarreau3842f002009-06-14 11:39:52 +02002031 curproxy->no_options &= ~cfg_opts[optnum].val;
2032 curproxy->options &= ~cfg_opts[optnum].val;
2033
2034 switch (kwm) {
2035 case KWM_STD:
2036 curproxy->options |= cfg_opts[optnum].val;
2037 break;
2038 case KWM_NO:
2039 curproxy->no_options |= cfg_opts[optnum].val;
2040 break;
2041 case KWM_DEF: /* already cleared */
2042 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002043 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002044
Willy Tarreau93893792009-07-23 13:19:11 +02002045 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002046 }
2047 }
2048
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002049 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2050 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002051 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2052 err_code |= ERR_WARN;
2053 goto out;
2054 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002055
Willy Tarreau3842f002009-06-14 11:39:52 +02002056 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2057 curproxy->options2 &= ~cfg_opts2[optnum].val;
2058
2059 switch (kwm) {
2060 case KWM_STD:
2061 curproxy->options2 |= cfg_opts2[optnum].val;
2062 break;
2063 case KWM_NO:
2064 curproxy->no_options2 |= cfg_opts2[optnum].val;
2065 break;
2066 case KWM_DEF: /* already cleared */
2067 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002068 }
Willy Tarreau93893792009-07-23 13:19:11 +02002069 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002070 }
2071 }
2072
Willy Tarreau3842f002009-06-14 11:39:52 +02002073 if (kwm != KWM_STD) {
2074 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002075 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002078 }
2079
Emeric Brun3a058f32009-06-30 18:26:00 +02002080 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002082 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002084 if (*(args[2]) != '\0') {
2085 if (!strcmp(args[2], "clf")) {
2086 curproxy->options2 |= PR_O2_CLFLOG;
2087 } else {
2088 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002091 }
2092 }
2093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 else if (!strcmp(args[1], "tcplog"))
2095 /* generate a detailed TCP log */
2096 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 else if (!strcmp(args[1], "tcpka")) {
2098 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002099 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002101
2102 if (curproxy->cap & PR_CAP_FE)
2103 curproxy->options |= PR_O_TCP_CLI_KA;
2104 if (curproxy->cap & PR_CAP_BE)
2105 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
2107 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002108 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002109 err_code |= ERR_WARN;
2110
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002112 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002113 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002114 curproxy->options &= ~PR_O_SMTP_CHK;
2115 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 if (!*args[2]) { /* no argument */
2117 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2118 curproxy->check_len = strlen(DEF_CHECK_REQ);
2119 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002120 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 curproxy->check_req = (char *)malloc(reqlen);
2122 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2123 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2124 } else { /* more arguments : METHOD URI [HTTP_VER] */
2125 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2126 if (*args[4])
2127 reqlen += strlen(args[4]);
2128 else
2129 reqlen += strlen("HTTP/1.0");
2130
2131 curproxy->check_req = (char *)malloc(reqlen);
2132 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2133 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2134 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002135 }
2136 else if (!strcmp(args[1], "ssl-hello-chk")) {
2137 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002138 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002139 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002140
Willy Tarreaua534fea2008-08-03 12:19:50 +02002141 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002142 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002143 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002144 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
Willy Tarreau23677902007-05-08 23:50:35 +02002146 else if (!strcmp(args[1], "smtpchk")) {
2147 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002148 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002149 curproxy->options &= ~PR_O_HTTP_CHK;
2150 curproxy->options &= ~PR_O_SSL3_CHK;
2151 curproxy->options |= PR_O_SMTP_CHK;
2152
2153 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2154 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2155 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2156 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2157 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2158 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2159 curproxy->check_req = (char *)malloc(reqlen);
2160 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2161 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2162 } else {
2163 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2164 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2165 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2166 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2167 }
2168 }
2169 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002170 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002171 int cur_arg;
2172
2173 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2174 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002175 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002176
2177 curproxy->options |= PR_O_FWDFOR;
2178
2179 free(curproxy->fwdfor_hdr_name);
2180 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2181 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2182
2183 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2184 cur_arg = 2;
2185 while (*(args[cur_arg])) {
2186 if (!strcmp(args[cur_arg], "except")) {
2187 /* suboption except - needs additional argument for it */
2188 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2189 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2190 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002193 }
2194 /* flush useless bits */
2195 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002196 cur_arg += 2;
2197 } else if (!strcmp(args[cur_arg], "header")) {
2198 /* suboption header - needs additional argument for it */
2199 if (*(args[cur_arg+1]) == 0) {
2200 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2201 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002204 }
2205 free(curproxy->fwdfor_hdr_name);
2206 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2207 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2208 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002209 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002210 /* unknown suboption - catchall */
2211 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2212 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002215 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002216 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002217 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002218 else if (!strcmp(args[1], "originalto")) {
2219 int cur_arg;
2220
2221 /* insert x-original-to field, but not for the IP address listed as an except.
2222 * set default options (ie: bitfield, header name, etc)
2223 */
2224
2225 curproxy->options |= PR_O_ORGTO;
2226
2227 free(curproxy->orgto_hdr_name);
2228 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2229 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2230
2231 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2232 cur_arg = 2;
2233 while (*(args[cur_arg])) {
2234 if (!strcmp(args[cur_arg], "except")) {
2235 /* suboption except - needs additional argument for it */
2236 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2237 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2238 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002241 }
2242 /* flush useless bits */
2243 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2244 cur_arg += 2;
2245 } else if (!strcmp(args[cur_arg], "header")) {
2246 /* suboption header - needs additional argument for it */
2247 if (*(args[cur_arg+1]) == 0) {
2248 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2249 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002252 }
2253 free(curproxy->orgto_hdr_name);
2254 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2255 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2256 cur_arg += 2;
2257 } else {
2258 /* unknown suboption - catchall */
2259 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2260 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002263 }
2264 } /* end while loop */
2265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 else {
2267 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
Willy Tarreau93893792009-07-23 13:19:11 +02002271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002273 else if (!strcmp(args[0], "default_backend")) {
2274 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002276
2277 if (*(args[1]) == 0) {
2278 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002281 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002282 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002283 curproxy->defbe.name = strdup(args[1]);
2284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002287 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002288
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002289 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2290 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 /* enable reconnections to dispatch */
2293 curproxy->options |= PR_O_REDISP;
2294 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002295 else if (!strcmp(args[0], "http-check")) {
2296 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002297 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002298
2299 if (strcmp(args[1], "disable-on-404") == 0) {
2300 /* enable a graceful server shutdown on an HTTP 404 response */
2301 curproxy->options |= PR_O_DISABLE404;
2302 }
2303 else {
2304 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002307 }
2308 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002309 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002310 if (curproxy == &defproxy) {
2311 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002314 }
2315
Willy Tarreaub80c2302007-11-30 20:51:32 +01002316 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002317 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002318
2319 if (strcmp(args[1], "fail") == 0) {
2320 /* add a condition to fail monitor requests */
2321 int pol = ACL_COND_NONE;
2322 struct acl_cond *cond;
2323
2324 if (!strcmp(args[2], "if"))
2325 pol = ACL_COND_IF;
2326 else if (!strcmp(args[2], "unless"))
2327 pol = ACL_COND_UNLESS;
2328
2329 if (pol == ACL_COND_NONE) {
2330 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2331 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002334 }
2335
2336 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2337 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2338 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002341 }
Willy Tarreaua9802632008-07-25 19:13:19 +02002342 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002343 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002344 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2345 }
2346 else {
2347 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002350 }
2351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352#ifdef TPROXY
2353 else if (!strcmp(args[0], "transparent")) {
2354 /* enable transparent proxy connections */
2355 curproxy->options |= PR_O_TRANSP;
2356 }
2357#endif
2358 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002361
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 if (*(args[1]) == 0) {
2363 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }
2367 curproxy->maxconn = atol(args[1]);
2368 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002369 else if (!strcmp(args[0], "backlog")) { /* backlog */
2370 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002372
2373 if (*(args[1]) == 0) {
2374 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002377 }
2378 curproxy->backlog = atol(args[1]);
2379 }
Willy Tarreau86034312006-12-29 00:10:33 +01002380 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002381 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002383
Willy Tarreau86034312006-12-29 00:10:33 +01002384 if (*(args[1]) == 0) {
2385 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002388 }
2389 curproxy->fullconn = atol(args[1]);
2390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2392 if (*(args[1]) == 0) {
2393 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002397 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2398 if (err) {
2399 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2400 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002403 }
2404 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 }
2406 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2407 if (curproxy == &defproxy) {
2408 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002412 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002414
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 if (strchr(args[1], ':') == NULL) {
2416 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420 curproxy->dispatch_addr = *str2sa(args[1]);
2421 }
2422 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002426 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002427 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2428 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 else if (!strcmp(args[0], "server")) { /* server address */
2434 int cur_arg;
2435 char *rport;
2436 char *raddr;
2437 short realport;
2438 int do_check;
2439
2440 if (curproxy == &defproxy) {
2441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447
2448 if (!*args[2]) {
2449 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002454
2455 err = invalid_char(args[1]);
2456 if (err) {
2457 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2458 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002461 }
2462
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2464 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_ABORT;
2466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
2468
2469 /* the servers are linked backwards first */
2470 newsrv->next = curproxy->srv;
2471 curproxy->srv = newsrv;
2472 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002473 newsrv->puid = curproxy->next_svid++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002474 newsrv->conf.file = file;
2475 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476
2477 LIST_INIT(&newsrv->pendconns);
2478 do_check = 0;
2479 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002480 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 newsrv->id = strdup(args[1]);
2482
2483 /* several ways to check the port component :
2484 * - IP => port=+0, relative
2485 * - IP: => port=+0, relative
2486 * - IP:N => port=N, absolute
2487 * - IP:+N => port=+N, relative
2488 * - IP:-N => port=-N, relative
2489 */
2490 raddr = strdup(args[2]);
2491 rport = strchr(raddr, ':');
2492 if (rport) {
2493 *rport++ = 0;
2494 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002495 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 newsrv->state |= SRV_MAPPORTS;
2497 } else {
2498 realport = 0;
2499 newsrv->state |= SRV_MAPPORTS;
2500 }
2501
2502 newsrv->addr = *str2sa(raddr);
2503 newsrv->addr.sin_port = htons(realport);
2504 free(raddr);
2505
2506 newsrv->curfd = -1; /* no health-check in progress */
2507 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002508 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2509 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 newsrv->rise = DEF_RISETIME;
2511 newsrv->fall = DEF_FALLTIME;
2512 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002513 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002514 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002515 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002516
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 cur_arg = 3;
2518 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002519 if (!strcmp(args[cur_arg], "id")) {
2520 struct server *target;
2521
2522 if (!*args[cur_arg + 1]) {
2523 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2524 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002527 }
2528
2529 newsrv->puid = atol(args[cur_arg + 1]);
2530
2531 if (newsrv->puid< 1001) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002532 Alert("parsing [%s:%d]: custom id has to be > 1000.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002533 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002536 }
2537
2538 for (target = proxy->srv; target; target = target->next)
2539 if (newsrv != target && newsrv->puid == target->puid) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002540 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2541 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002544 }
2545 cur_arg += 2;
2546 }
2547 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 newsrv->cookie = strdup(args[cur_arg + 1]);
2549 newsrv->cklen = strlen(args[cur_arg + 1]);
2550 cur_arg += 2;
2551 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002552 else if (!strcmp(args[cur_arg], "redir")) {
2553 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2554 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2555 cur_arg += 2;
2556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002558 if (!*args[cur_arg + 1]) {
2559 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2560 file, linenum, args[cur_arg]);
2561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
2563 }
2564
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002566 if (newsrv->rise <= 0) {
2567 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2568 file, linenum, args[cur_arg]);
2569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
2571 }
2572
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 newsrv->health = newsrv->rise;
2574 cur_arg += 2;
2575 }
2576 else if (!strcmp(args[cur_arg], "fall")) {
2577 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002578
2579 if (!*args[cur_arg + 1]) {
2580 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2581 file, linenum, args[cur_arg]);
2582 err_code |= ERR_ALERT | ERR_FATAL;
2583 goto out;
2584 }
2585
2586 if (newsrv->fall <= 0) {
2587 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2588 file, linenum, args[cur_arg]);
2589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
2591 }
2592
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 cur_arg += 2;
2594 }
2595 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002596 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2597 if (err) {
2598 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2599 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002602 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002603 if (val <= 0) {
2604 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2605 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002608 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002609 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 cur_arg += 2;
2611 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002612 else if (!strcmp(args[cur_arg], "fastinter")) {
2613 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2614 if (err) {
2615 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2616 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002619 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002620 if (val <= 0) {
2621 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2622 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002625 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002626 newsrv->fastinter = val;
2627 cur_arg += 2;
2628 }
2629 else if (!strcmp(args[cur_arg], "downinter")) {
2630 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2631 if (err) {
2632 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2633 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002636 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002637 if (val <= 0) {
2638 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2639 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002642 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002643 newsrv->downinter = val;
2644 cur_arg += 2;
2645 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002646 else if (!strcmp(args[cur_arg], "addr")) {
2647 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002648 cur_arg += 2;
2649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 else if (!strcmp(args[cur_arg], "port")) {
2651 newsrv->check_port = atol(args[cur_arg + 1]);
2652 cur_arg += 2;
2653 }
2654 else if (!strcmp(args[cur_arg], "backup")) {
2655 newsrv->state |= SRV_BACKUP;
2656 cur_arg ++;
2657 }
2658 else if (!strcmp(args[cur_arg], "weight")) {
2659 int w;
2660 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002661 if (w < 0 || w > 256) {
2662 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002667 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 cur_arg += 2;
2669 }
2670 else if (!strcmp(args[cur_arg], "minconn")) {
2671 newsrv->minconn = atol(args[cur_arg + 1]);
2672 cur_arg += 2;
2673 }
2674 else if (!strcmp(args[cur_arg], "maxconn")) {
2675 newsrv->maxconn = atol(args[cur_arg + 1]);
2676 cur_arg += 2;
2677 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002678 else if (!strcmp(args[cur_arg], "maxqueue")) {
2679 newsrv->maxqueue = atol(args[cur_arg + 1]);
2680 cur_arg += 2;
2681 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002682 else if (!strcmp(args[cur_arg], "slowstart")) {
2683 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002684 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002685 if (err) {
2686 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2687 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002690 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002691 if (val <= 0) {
2692 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2693 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002696 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002697 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002698 cur_arg += 2;
2699 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002700 else if (!strcmp(args[cur_arg], "track")) {
2701
2702 if (!*args[cur_arg + 1]) {
2703 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2704 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002707 }
2708
2709 newsrv->trackit = strdup(args[cur_arg + 1]);
2710
2711 cur_arg += 2;
2712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 else if (!strcmp(args[cur_arg], "check")) {
2714 global.maxsock++;
2715 do_check = 1;
2716 cur_arg += 1;
2717 }
2718 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002719 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002721#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002722 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002723 file, linenum, "source", "usesrc");
2724#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002725 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002727#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 }
2731 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002732 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2733
2734 if (port_low != port_high) {
2735 int i;
2736 if (port_low <= 0 || port_low > 65535 ||
2737 port_high <= 0 || port_high > 65535 ||
2738 port_low > port_high) {
2739 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2740 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002743 }
2744 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2745 for (i = 0; i < newsrv->sport_range->size; i++)
2746 newsrv->sport_range->ports[i] = port_low + i;
2747 }
2748
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002750 while (*(args[cur_arg])) {
2751 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002752#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2753#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002754 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2755 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2756 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002759 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002760#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002761 if (!*args[cur_arg + 1]) {
2762 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2763 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002766 }
2767 if (!strcmp(args[cur_arg + 1], "client")) {
2768 newsrv->state |= SRV_TPROXY_CLI;
2769 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2770 newsrv->state |= SRV_TPROXY_CIP;
2771 } else {
2772 newsrv->state |= SRV_TPROXY_ADDR;
2773 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2774 }
2775 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002776#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002777 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002778#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002779 cur_arg += 2;
2780 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002781#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002782 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002783 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002786#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2787 } /* "usesrc" */
2788
2789 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2790#ifdef SO_BINDTODEVICE
2791 if (!*args[cur_arg + 1]) {
2792 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2793 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002796 }
2797 if (newsrv->iface_name)
2798 free(newsrv->iface_name);
2799
2800 newsrv->iface_name = strdup(args[cur_arg + 1]);
2801 newsrv->iface_len = strlen(newsrv->iface_name);
2802 global.last_checks |= LSTCHK_NETADM;
2803#else
2804 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2805 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002808#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002809 cur_arg += 2;
2810 continue;
2811 }
2812 /* this keyword in not an option of "source" */
2813 break;
2814 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002816 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2817 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2818 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002821 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002823 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 +02002824 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 }
2828 }
2829
2830 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002831 if (newsrv->trackit) {
2832 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2833 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002836 }
2837
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002838 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2839 newsrv->check_port = newsrv->check_addr.sin_port;
2840
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2842 newsrv->check_port = realport; /* by default */
2843 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002844 /* not yet valid, because no port was set on
2845 * the server either. We'll check if we have
2846 * a known port on the first listener.
2847 */
2848 struct listener *l;
2849 l = curproxy->listen;
2850 if (l) {
2851 int port;
2852 port = (l->addr.ss_family == AF_INET6)
2853 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2854 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2855 newsrv->check_port = port;
2856 }
2857 }
2858 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2860 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02002864
2865 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 newsrv->state |= SRV_CHECKED;
2867 }
2868
2869 if (newsrv->state & SRV_BACKUP)
2870 curproxy->srv_bck++;
2871 else
2872 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002873
2874 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
2876 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002877 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 int facility;
2879
2880 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2881 curproxy->logfac1 = global.logfac1;
2882 curproxy->logsrv1 = global.logsrv1;
2883 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002884 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 curproxy->logfac2 = global.logfac2;
2886 curproxy->logsrv2 = global.logsrv2;
2887 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002888 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }
2890 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002891 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892
2893 facility = get_log_facility(args[2]);
2894 if (facility < 0) {
2895 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2896 exit(1);
2897 }
2898
2899 level = 7; /* max syslog level = debug */
2900 if (*(args[3])) {
2901 level = get_log_level(args[3]);
2902 if (level < 0) {
2903 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2904 exit(1);
2905 }
2906 }
2907
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002908 minlvl = 0; /* limit syslog level to this level (emerg) */
2909 if (*(args[4])) {
2910 minlvl = get_log_level(args[4]);
2911 if (level < 0) {
2912 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2913 exit(1);
2914 }
2915 }
2916
Robert Tsai81ae1952007-12-05 10:47:29 +01002917 if (args[1][0] == '/') {
2918 logsrv.u.addr.sa_family = AF_UNIX;
2919 logsrv.u.un = *str2sun(args[1]);
2920 } else {
2921 logsrv.u.addr.sa_family = AF_INET;
2922 logsrv.u.in = *str2sa(args[1]);
2923 if (!logsrv.u.in.sin_port) {
2924 logsrv.u.in.sin_port =
2925 htons(SYSLOG_PORT);
2926 }
2927 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928
2929 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002930 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 curproxy->logfac1 = facility;
2932 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002933 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 }
2935 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002936 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 curproxy->logfac2 = facility;
2938 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002939 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 }
2941 else {
2942 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 }
2946 }
2947 else {
2948 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2949 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 }
2953 }
2954 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002955 int cur_arg;
2956
Willy Tarreau977b8e42006-12-29 14:19:17 +01002957 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002958 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002959
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002961 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2962 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002966
2967 /* we must first clear any optional default setting */
2968 curproxy->options &= ~PR_O_TPXY_MASK;
2969 free(curproxy->iface_name);
2970 curproxy->iface_name = NULL;
2971 curproxy->iface_len = 0;
2972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 curproxy->source_addr = *str2sa(args[1]);
2974 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002975
2976 cur_arg = 2;
2977 while (*(args[cur_arg])) {
2978 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002979#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2980#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002981 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2982 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2983 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002986 }
2987#endif
2988 if (!*args[cur_arg + 1]) {
2989 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2990 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002993 }
2994
2995 if (!strcmp(args[cur_arg + 1], "client")) {
2996 curproxy->options |= PR_O_TPXY_CLI;
2997 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2998 curproxy->options |= PR_O_TPXY_CIP;
2999 } else {
3000 curproxy->options |= PR_O_TPXY_ADDR;
3001 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3002 }
3003 global.last_checks |= LSTCHK_NETADM;
3004#if !defined(CONFIG_HAP_LINUX_TPROXY)
3005 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003006#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003007#else /* no TPROXY support */
3008 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003009 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003012#endif
3013 cur_arg += 2;
3014 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003015 }
3016
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003017 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3018#ifdef SO_BINDTODEVICE
3019 if (!*args[cur_arg + 1]) {
3020 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003024 }
3025 if (curproxy->iface_name)
3026 free(curproxy->iface_name);
3027
3028 curproxy->iface_name = strdup(args[cur_arg + 1]);
3029 curproxy->iface_len = strlen(curproxy->iface_name);
3030 global.last_checks |= LSTCHK_NETADM;
3031#else
3032 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3033 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003036#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003037 cur_arg += 2;
3038 continue;
3039 }
3040 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3041 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003046 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3047 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3048 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3053 regex_t *preg;
3054 if (curproxy == &defproxy) {
3055 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003059 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003061
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 if (*(args[1]) == 0 || *(args[2]) == 0) {
3063 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 }
3068
3069 preg = calloc(1, sizeof(regex_t));
3070 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3071 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
3075
3076 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3077 if (err) {
3078 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3079 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003082 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
3084 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3085 regex_t *preg;
3086 if (curproxy == &defproxy) {
3087 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003091 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003093
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 if (*(args[1]) == 0) {
3095 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 }
3099
3100 preg = calloc(1, sizeof(regex_t));
3101 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3102 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 }
3106
3107 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003108 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
3110 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3111 regex_t *preg;
3112 if (curproxy == &defproxy) {
3113 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003117 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003119
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 if (*(args[1]) == 0) {
3121 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 }
3125
3126 preg = calloc(1, sizeof(regex_t));
3127 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3128 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
3132
3133 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003134 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
3136 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3137 regex_t *preg;
3138 if (curproxy == &defproxy) {
3139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003143 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003144 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003145
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 if (*(args[1]) == 0) {
3147 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 }
3151
3152 preg = calloc(1, sizeof(regex_t));
3153 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3154 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 }
3158
3159 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003160 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
3162 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3163 regex_t *preg;
3164 if (curproxy == &defproxy) {
3165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003169 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003171
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 if (*(args[1]) == 0) {
3173 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 }
3177
3178 preg = calloc(1, sizeof(regex_t));
3179 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3180 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 }
3184
3185 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003186 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003188 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3189 regex_t *preg;
3190 if (curproxy == &defproxy) {
3191 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003194 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003195 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003197
Willy Tarreaub8750a82006-09-03 09:56:00 +02003198 if (*(args[1]) == 0) {
3199 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003202 }
3203
3204 preg = calloc(1, sizeof(regex_t));
3205 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3206 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003209 }
3210
3211 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003212 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003213 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003214 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3215 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003216 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003217 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003220 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003221 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003223
Willy Tarreau977b8e42006-12-29 14:19:17 +01003224 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003225 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3226 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003229 }
3230
3231 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003232 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003233 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003236 }
3237
3238 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003239 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003240 }
3241 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3242 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003243 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003244 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003247 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003248 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003249 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003250
Willy Tarreau977b8e42006-12-29 14:19:17 +01003251 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003252 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003256 }
3257
3258 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003259 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003260 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003263 }
3264
3265 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003266 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3269 regex_t *preg;
3270 if (curproxy == &defproxy) {
3271 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003275 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003277
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 if (*(args[1]) == 0 || *(args[2]) == 0) {
3279 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3280 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
3284
3285 preg = calloc(1, sizeof(regex_t));
3286 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3287 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 }
3291
3292 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3293 if (err) {
3294 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3295 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003299 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3302 regex_t *preg;
3303 if (curproxy == &defproxy) {
3304 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003308 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003310
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 if (*(args[1]) == 0) {
3312 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }
3316
3317 preg = calloc(1, sizeof(regex_t));
3318 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3319 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
3323
3324 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003325 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
3327 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3328 regex_t *preg;
3329 if (curproxy == &defproxy) {
3330 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003334 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003336
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 if (*(args[1]) == 0) {
3338 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 }
3342
3343 preg = calloc(1, sizeof(regex_t));
3344 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3345 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
3349
3350 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003351 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
3353 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3354 regex_t *preg;
3355 if (curproxy == &defproxy) {
3356 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003360 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003362
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 if (*(args[1]) == 0) {
3364 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
3368
3369 preg = calloc(1, sizeof(regex_t));
3370 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3371 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
3375
3376 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003377 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
3379 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3380 regex_t *preg;
3381 if (curproxy == &defproxy) {
3382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003386 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003388
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 if (*(args[1]) == 0) {
3390 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394
3395 preg = calloc(1, sizeof(regex_t));
3396 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3397 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
3401
3402 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003403 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003405 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3406 regex_t *preg;
3407 if (curproxy == &defproxy) {
3408 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003411 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003412 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003414
Willy Tarreaub8750a82006-09-03 09:56:00 +02003415 if (*(args[1]) == 0) {
3416 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003419 }
3420
3421 preg = calloc(1, sizeof(regex_t));
3422 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3423 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003426 }
3427
3428 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003429 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3432 if (curproxy == &defproxy) {
3433 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003437 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003438 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439
3440 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3441 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 }
3445
3446 if (*(args[1]) == 0) {
3447 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003450 }
3451
3452 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003453 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003454 }
3455 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3456 regex_t *preg;
3457
3458 if (*(args[1]) == 0 || *(args[2]) == 0) {
3459 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003464 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003466
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 preg = calloc(1, sizeof(regex_t));
3468 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3469 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472 }
3473
3474 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3475 if (err) {
3476 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3477 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003481 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 }
3483 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3484 regex_t *preg;
3485 if (curproxy == &defproxy) {
3486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003490 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003492
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 if (*(args[1]) == 0) {
3494 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 }
3498
3499 preg = calloc(1, sizeof(regex_t));
3500 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3501 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 }
3505
3506 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3507 if (err) {
3508 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3509 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 }
3513 }
3514 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3515 regex_t *preg;
3516 if (curproxy == &defproxy) {
3517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003521 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003523
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 if (*(args[1]) == 0) {
3525 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
3529
3530 preg = calloc(1, sizeof(regex_t));
3531 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3532 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 }
3536
3537 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3538 if (err) {
3539 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3540 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
3544 }
3545 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3546 regex_t *preg;
3547 if (curproxy == &defproxy) {
3548 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003552 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554
3555 if (*(args[1]) == 0 || *(args[2]) == 0) {
3556 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 }
3561
3562 preg = calloc(1, sizeof(regex_t));
3563 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3564 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 }
3568
3569 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3570 if (err) {
3571 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3572 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 }
3576 }
3577 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3578 regex_t *preg;
3579 if (curproxy == &defproxy) {
3580 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003584 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003586
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 if (*(args[1]) == 0) {
3588 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
3592
3593 preg = calloc(1, sizeof(regex_t));
3594 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3595 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
3599
3600 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3601 if (err) {
3602 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3603 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
3607 }
3608 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3609 regex_t *preg;
3610 if (curproxy == &defproxy) {
3611 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003615 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003617
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 if (*(args[1]) == 0) {
3619 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
3623
3624 preg = calloc(1, sizeof(regex_t));
3625 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3626 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 }
3630
3631 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3632 if (err) {
3633 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3634 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 }
3638 }
3639 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3640 if (curproxy == &defproxy) {
3641 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003645 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647
3648 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3649 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
3653
3654 if (*(args[1]) == 0) {
3655 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 }
3659
3660 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3661 }
3662 else if (!strcmp(args[0], "errorloc") ||
3663 !strcmp(args[0], "errorloc302") ||
3664 !strcmp(args[0], "errorloc303")) { /* error location */
3665 int errnum, errlen;
3666 char *err;
3667
Willy Tarreau977b8e42006-12-29 14:19:17 +01003668 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003670
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003672 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 }
3676
3677 errnum = atol(args[1]);
3678 if (!strcmp(args[0], "errorloc303")) {
3679 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3680 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3681 } else {
3682 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3683 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3684 }
3685
Willy Tarreau0f772532006-12-23 20:51:41 +01003686 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3687 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003688 chunk_destroy(&curproxy->errmsg[rc]);
3689 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003690 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003693
3694 if (rc >= HTTP_ERR_SIZE) {
3695 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3696 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 free(err);
3698 }
3699 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003700 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3701 int errnum, errlen, fd;
3702 char *err;
3703 struct stat stat;
3704
3705 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003707
3708 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003709 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003712 }
3713
3714 fd = open(args[2], O_RDONLY);
3715 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3716 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3717 file, linenum, args[2], args[1]);
3718 if (fd >= 0)
3719 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003722 }
3723
Willy Tarreau27a674e2009-08-17 07:23:33 +02003724 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003725 errlen = stat.st_size;
3726 } else {
3727 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003728 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003730 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003731 }
3732
3733 err = malloc(errlen); /* malloc() must succeed during parsing */
3734 errnum = read(fd, err, errlen);
3735 if (errnum != errlen) {
3736 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3737 file, linenum, args[2], args[1]);
3738 close(fd);
3739 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003742 }
3743 close(fd);
3744
3745 errnum = atol(args[1]);
3746 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3747 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003748 chunk_destroy(&curproxy->errmsg[rc]);
3749 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003750 break;
3751 }
3752 }
3753
3754 if (rc >= HTTP_ERR_SIZE) {
3755 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3756 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003758 free(err);
3759 }
3760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003762 struct cfg_kw_list *kwl;
3763 int index;
3764
3765 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3766 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3767 if (kwl->kw[index].section != CFG_LISTEN)
3768 continue;
3769 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3770 /* prepare error message just in case */
3771 snprintf(trash, sizeof(trash),
3772 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003773 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3774 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003775 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003778 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003779 else if (rc > 0) {
3780 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_WARN;
3782 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003783 }
Willy Tarreau93893792009-07-23 13:19:11 +02003784 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003785 }
3786 }
3787 }
3788
Willy Tarreau6daf3432008-01-22 16:44:08 +01003789 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 }
Willy Tarreau93893792009-07-23 13:19:11 +02003793 out:
3794 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795}
3796
3797
3798/*
3799 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003800 * Returns the error code, 0 if OK, or any combination of :
3801 * - ERR_ABORT: must abort ASAP
3802 * - ERR_FATAL: we can continue parsing but not start the service
3803 * - ERR_WARN: a warning has been emitted
3804 * - ERR_ALERT: an alert has been emitted
3805 * Only the two first ones can stop processing, the two others are just
3806 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003808int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003810 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 FILE *f;
3812 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003814 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 if ((f=fopen(file,"r")) == NULL)
3817 return -1;
3818
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003819 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003820 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003821 char *end;
3822 char *args[MAX_LINE_ARGS + 1];
3823 char *line = thisline;
3824
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 linenum++;
3826
3827 end = line + strlen(line);
3828
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003829 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3830 /* Check if we reached the limit and the last char is not \n.
3831 * Watch out for the last line without the terminating '\n'!
3832 */
3833 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003834 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003836 }
3837
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003839 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 line++;
3841
3842 arg = 0;
3843 args[arg] = line;
3844
3845 while (*line && arg < MAX_LINE_ARGS) {
3846 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3847 * C equivalent value. Other combinations left unchanged (eg: \1).
3848 */
3849 if (*line == '\\') {
3850 int skip = 0;
3851 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3852 *line = line[1];
3853 skip = 1;
3854 }
3855 else if (line[1] == 'r') {
3856 *line = '\r';
3857 skip = 1;
3858 }
3859 else if (line[1] == 'n') {
3860 *line = '\n';
3861 skip = 1;
3862 }
3863 else if (line[1] == 't') {
3864 *line = '\t';
3865 skip = 1;
3866 }
3867 else if (line[1] == 'x') {
3868 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3869 unsigned char hex1, hex2;
3870 hex1 = toupper(line[2]) - '0';
3871 hex2 = toupper(line[3]) - '0';
3872 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3873 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3874 *line = (hex1<<4) + hex2;
3875 skip = 3;
3876 }
3877 else {
3878 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
3881 }
3882 if (skip) {
3883 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3884 end -= skip;
3885 }
3886 line++;
3887 }
3888 else if (*line == '#' || *line == '\n' || *line == '\r') {
3889 /* end of string, end of loop */
3890 *line = 0;
3891 break;
3892 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003893 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003895 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003896 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 line++;
3898 args[++arg] = line;
3899 }
3900 else {
3901 line++;
3902 }
3903 }
3904
3905 /* empty line */
3906 if (!**args)
3907 continue;
3908
Willy Tarreau540abe42007-05-02 20:50:16 +02003909 /* zero out remaining args and ensure that at least one entry
3910 * is zeroed out.
3911 */
3912 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003913 args[arg] = line;
3914 }
3915
Willy Tarreau3842f002009-06-14 11:39:52 +02003916 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003917 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003918 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003919 for (arg=0; *args[arg+1]; arg++)
3920 args[arg] = args[arg+1]; // shift args after inversion
3921 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003922 else if (!strcmp(args[0], "default")) {
3923 kwm = KWM_DEF;
3924 for (arg=0; *args[arg+1]; arg++)
3925 args[arg] = args[arg+1]; // shift args after inversion
3926 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003927
Willy Tarreau3842f002009-06-14 11:39:52 +02003928 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3929 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003931 }
3932
Willy Tarreau977b8e42006-12-29 14:19:17 +01003933 if (!strcmp(args[0], "listen") ||
3934 !strcmp(args[0], "frontend") ||
3935 !strcmp(args[0], "backend") ||
3936 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003937 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003939 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003940 cursection = strdup(args[0]);
3941 }
3942 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003944 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003945 cursection = strdup(args[0]);
3946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 /* else it's a section keyword */
3948
3949 switch (confsect) {
3950 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 break;
3953 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003954 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 break;
3956 default:
3957 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003960
3961 if (err_code & ERR_ABORT)
3962 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003964 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003965 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003966 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003967 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003968}
3969
Willy Tarreaubb925012009-07-23 13:36:36 +02003970/*
3971 * Returns the error code, 0 if OK, or any combination of :
3972 * - ERR_ABORT: must abort ASAP
3973 * - ERR_FATAL: we can continue parsing but not start the service
3974 * - ERR_WARN: a warning has been emitted
3975 * - ERR_ALERT: an alert has been emitted
3976 * Only the two first ones can stop processing, the two others are just
3977 * indicators.
3978 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003979int check_config_validity()
3980{
3981 int cfgerr = 0;
3982 struct proxy *curproxy = NULL;
3983 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003984 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985
3986 /*
3987 * Now, check for the integrity of all that we have collected.
3988 */
3989
3990 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003991 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003993 /* first, we will invert the proxy list order */
3994 curproxy = NULL;
3995 while (proxy) {
3996 struct proxy *next;
3997
3998 next = proxy->next;
3999 proxy->next = curproxy;
4000 curproxy = proxy;
4001 if (!next)
4002 break;
4003 proxy = next;
4004 }
4005
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004007 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 }
4011
4012 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004013 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004014 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004015
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004017 /* ensure we don't keep listeners uselessly bound */
4018 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 curproxy = curproxy->next;
4020 continue;
4021 }
4022
Willy Tarreauff01a212009-03-15 13:46:16 +01004023 switch (curproxy->mode) {
4024 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004025 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004026 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004027 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4028 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004029 cfgerr++;
4030 }
4031
4032 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004033 Warning("config : servers will be ignored for %s '%s'.\n",
4034 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004035 break;
4036
4037 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004038 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004039 break;
4040
4041 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004042 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004043 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004044 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4045 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004046 cfgerr++;
4047 }
4048 break;
4049 }
4050
4051 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004052 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4053 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 cfgerr++;
4055 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004056
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004057 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004058 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004059 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004060 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4061 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004062 cfgerr++;
4063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004065 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004066 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4067 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004068 cfgerr++;
4069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004071 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004072 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4073 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004074 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004075 }
4076 }
4077 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4078 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4079 /* If no LB algo is set in a backend, and we're not in
4080 * transparent mode, dispatch mode nor proxy mode, we
4081 * want to use balance roundrobin by default.
4082 */
4083 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4084 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004085 }
4086 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004087
Willy Tarreau82936582007-11-30 15:20:09 +01004088 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4089 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004090 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4091 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004092 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004093 }
4094
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004095 /* if a default backend was specified, let's find it */
4096 if (curproxy->defbe.name) {
4097 struct proxy *target;
4098
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004099 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
4100 if (!target) {
4101 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4102 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004103 cfgerr++;
4104 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004105 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4106 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004107 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004108 } else {
4109 free(curproxy->defbe.name);
4110 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004111 /* we force the backend to be present on at least all of
4112 * the frontend's processes.
4113 */
4114 target->bind_proc = curproxy->bind_proc ?
4115 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 }
4117 }
4118
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004119 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004120 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4121 /* map jump target for ACT_SETBE in req_rep chain */
4122 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004123 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004124 struct proxy *target;
4125
Willy Tarreaua496b602006-12-17 23:15:24 +01004126 if (exp->action != ACT_SETBE)
4127 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004128
4129 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
4130 if (!target) {
4131 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4132 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004133 cfgerr++;
4134 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004135 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4136 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004137 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004138 } else {
4139 free((void *)exp->replace);
4140 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004141 /* we force the backend to be present on at least all of
4142 * the frontend's processes.
4143 */
4144 target->bind_proc = curproxy->bind_proc ?
4145 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004146 }
4147 }
4148 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004149
4150 /* find the target proxy for 'use_backend' rules */
4151 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004152 struct proxy *target;
4153
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004154 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004155
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004156 if (!target) {
4157 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4158 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004159 cfgerr++;
4160 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004161 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4162 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004163 cfgerr++;
4164 } else {
4165 free((void *)rule->be.name);
4166 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004167 /* we force the backend to be present on at least all of
4168 * the frontend's processes.
4169 */
4170 target->bind_proc = curproxy->bind_proc ?
4171 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004172 }
4173 }
4174
Willy Tarreau2738a142006-07-08 17:28:09 +02004175 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004176 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004177 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004178 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004179 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004180 " | While not properly invalid, you will certainly encounter various problems\n"
4181 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004182 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004183 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004184 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004185 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004186
Willy Tarreau1fa31262007-12-03 00:36:16 +01004187 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4188 * We must still support older configurations, so let's find out whether those
4189 * parameters have been set or must be copied from contimeouts.
4190 */
4191 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004192 if (!curproxy->timeout.tarpit ||
4193 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004194 /* tarpit timeout not set. We search in the following order:
4195 * default.tarpit, curr.connect, default.connect.
4196 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004197 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004198 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004199 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004200 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004201 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004202 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004203 }
4204 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004205 (!curproxy->timeout.queue ||
4206 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004207 /* queue timeout not set. We search in the following order:
4208 * default.queue, curr.connect, default.connect.
4209 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004210 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004211 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004212 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004213 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004214 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004215 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004216 }
4217 }
4218
Willy Tarreauf3c69202006-07-09 16:42:34 +02004219 if (curproxy->options & PR_O_SSL3_CHK) {
4220 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4221 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4222 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4223 }
4224
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004225 /* The small pools required for the capture lists */
4226 if (curproxy->nb_req_cap)
4227 curproxy->req_cap_pool = create_pool("ptrcap",
4228 curproxy->nb_req_cap * sizeof(char *),
4229 MEM_F_SHARED);
4230 if (curproxy->nb_rsp_cap)
4231 curproxy->rsp_cap_pool = create_pool("ptrcap",
4232 curproxy->nb_rsp_cap * sizeof(char *),
4233 MEM_F_SHARED);
4234
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004235 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4236 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4237 MEM_F_SHARED);
4238
Willy Tarreau86034312006-12-29 00:10:33 +01004239 /* for backwards compatibility with "listen" instances, if
4240 * fullconn is not set but maxconn is set, then maxconn
4241 * is used.
4242 */
4243 if (!curproxy->fullconn)
4244 curproxy->fullconn = curproxy->maxconn;
4245
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 /* first, we will invert the servers list order */
4247 newsrv = NULL;
4248 while (curproxy->srv) {
4249 struct server *next;
4250
4251 next = curproxy->srv->next;
4252 curproxy->srv->next = newsrv;
4253 newsrv = curproxy->srv;
4254 if (!next)
4255 break;
4256 curproxy->srv = next;
4257 }
4258
Willy Tarreau20697042007-11-15 23:26:18 +01004259 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004260 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004262 /* We have to initialize the server lookup mechanism depending
4263 * on what LB algorithm was choosen.
4264 */
4265
4266 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4267 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4268 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004269 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4270 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4271 init_server_map(curproxy);
4272 } else {
4273 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4274 fwrr_init_server_groups(curproxy);
4275 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004276 break;
4277 case BE_LB_KIND_LC:
4278 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004279 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004280 break;
4281 case BE_LB_KIND_HI:
4282 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
Willy Tarreaub625a082007-11-26 01:15:43 +01004283 init_server_map(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004284 break;
4285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286
4287 if (curproxy->options & PR_O_LOGASAP)
4288 curproxy->to_log &= ~LW_BYTES;
4289
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004290 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4291 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4292 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4293 proxy_type_str(curproxy), curproxy->id);
4294 err_code |= ERR_WARN;
4295 }
4296
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004298 * ensure that we're not cross-dressing a TCP server into HTTP.
4299 */
4300 newsrv = curproxy->srv;
4301 while (newsrv != NULL) {
4302 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004303 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4304 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004305 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004306 }
4307 newsrv = newsrv->next;
4308 }
4309
4310 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 * If this server supports a maxconn parameter, it needs a dedicated
4312 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004313 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 */
4315 newsrv = curproxy->srv;
4316 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004317 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004318 /* Only 'minconn' was specified, or it was higher than or equal
4319 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4320 * this will avoid further useless expensive computations.
4321 */
4322 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004323 } else if (newsrv->maxconn && !newsrv->minconn) {
4324 /* minconn was not specified, so we set it to maxconn */
4325 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004326 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004327 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4328 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004329 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 }
4331
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004332 if (newsrv->trackit) {
4333 struct proxy *px;
4334 struct server *srv;
4335 char *pname, *sname;
4336
4337 pname = newsrv->trackit;
4338 sname = strrchr(pname, '/');
4339
4340 if (sname)
4341 *sname++ = '\0';
4342 else {
4343 sname = pname;
4344 pname = NULL;
4345 }
4346
4347 if (pname) {
4348 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4349 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004350 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4351 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004352 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004353 cfgerr++;
4354 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004355 }
4356 } else
4357 px = curproxy;
4358
4359 srv = findserver(px, sname);
4360 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004361 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4362 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004363 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004364 cfgerr++;
4365 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004366 }
4367
4368 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004369 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004370 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004371 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004372 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004373 cfgerr++;
4374 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004375 }
4376
4377 if (curproxy != px &&
4378 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004379 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004380 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004381 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004382 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004383 cfgerr++;
4384 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004385 }
4386
4387 newsrv->tracked = srv;
4388 newsrv->tracknext = srv->tracknext;
4389 srv->tracknext = newsrv;
4390
4391 free(newsrv->trackit);
4392 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004393 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 newsrv = newsrv->next;
4395 }
4396
Willy Tarreauc1a21672009-08-16 22:37:44 +02004397 if (curproxy->cap & PR_CAP_FE) {
4398 if (curproxy->tcp_req.inspect_delay ||
4399 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4400 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4401
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004402 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004403 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004404 curproxy->fe_rsp_ana |= AN_RTR_HTTP_HDR;
4405 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004406
4407 /* both TCP and HTTP must check switching rules */
4408 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4409 }
4410
4411 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004412 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004413 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004414 curproxy->be_rsp_ana |= AN_RTR_HTTP_HDR;
4415 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004416
4417 /* If the backend does requires RDP cookie persistence, we have to
4418 * enable the corresponding analyser.
4419 */
4420 if (curproxy->options2 & PR_O2_RDPC_PRST)
4421 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4422 }
4423
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004424 listener = NULL;
4425 while (curproxy->listen) {
4426 struct listener *next;
4427
4428 next = curproxy->listen->next;
4429 curproxy->listen->next = listener;
4430 listener = curproxy->listen;
4431
4432 if (!next)
4433 break;
4434
4435 curproxy->listen = next;
4436 }
4437
Willy Tarreaue6b98942007-10-29 01:09:36 +01004438 /* adjust this proxy's listeners */
4439 listener = curproxy->listen;
4440 while (listener) {
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004441 /* enable separate counters */
4442 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4443 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4444 if (!listener->name) {
4445 sprintf(trash, "sock-%d", listener->luid);
4446 listener->name = strdup(trash);
4447 }
4448 }
4449
Willy Tarreaue6b98942007-10-29 01:09:36 +01004450 if (curproxy->options & PR_O_TCP_NOLING)
4451 listener->options |= LI_O_NOLINGER;
4452 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004453 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004454 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004455 listener->accept = event_accept;
4456 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004457 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004458 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004459
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004460 /* smart accept mode is automatic in HTTP mode */
4461 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4462 (curproxy->mode == PR_MODE_HTTP &&
4463 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4464 listener->options |= LI_O_NOQUICKACK;
4465
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004466 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004467 listener = listener->next;
4468 }
4469
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470 curproxy = curproxy->next;
4471 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004472
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004473 /*
4474 * Recount currently required checks.
4475 */
4476
4477 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4478 int optnum;
4479
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004480 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4481 if (curproxy->options & cfg_opts[optnum].val)
4482 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004483
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004484 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4485 if (curproxy->options2 & cfg_opts2[optnum].val)
4486 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004487 }
4488
Willy Tarreaubb925012009-07-23 13:36:36 +02004489 if (cfgerr > 0)
4490 err_code |= ERR_ALERT | ERR_FATAL;
4491 out:
4492 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493}
4494
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004495/*
4496 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4497 * parsing sessions.
4498 */
4499void cfg_register_keywords(struct cfg_kw_list *kwl)
4500{
4501 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4502}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004504/*
4505 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4506 */
4507void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4508{
4509 LIST_DEL(&kwl->list);
4510 LIST_INIT(&kwl->list);
4511}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512
4513/*
4514 * Local variables:
4515 * c-indent-level: 8
4516 * c-basic-offset: 8
4517 * End:
4518 */