blob: 978162386ee85ceb996ead69b6b3327abef93592 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
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 Tarreau6b2e11b2009-10-01 07:52:15 +020045#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020046#include <proto/lb_fwlc.h>
47#include <proto/lb_fwrr.h>
48#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020050#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010051#include <proto/protocols.h>
52#include <proto/proto_tcp.h>
53#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010054#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010056#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/task.h>
58
59
Willy Tarreauf3c69202006-07-09 16:42:34 +020060/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
61 * ssl-hello-chk option to ensure that the remote server speaks SSL.
62 *
63 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
64 */
65const char sslv3_client_hello_pkt[] = {
66 "\x16" /* ContentType : 0x16 = Hanshake */
67 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
68 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
69 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
70 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
71 "\x03\x00" /* Hello Version : 0x0300 = v3 */
72 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
73 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
74 "\x00" /* Session ID length : empty (no session ID) */
75 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
76 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
77 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
78 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
79 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
80 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
81 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
82 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
83 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
84 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
85 "\x00\x38" "\x00\x39" "\x00\x3A"
86 "\x01" /* Compression Length : 0x01 = 1 byte for types */
87 "\x00" /* Compression Type : 0x00 = NULL compression */
88};
89
Willy Tarreau3842f002009-06-14 11:39:52 +020090/* various keyword modifiers */
91enum kw_mod {
92 KWM_STD = 0, /* normal */
93 KWM_NO, /* "no" prefixed before the keyword */
94 KWM_DEF, /* "default" prefixed before the keyword */
95};
96
Willy Tarreau13943ab2006-12-31 00:24:10 +010097/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010098struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010099 const char *name;
100 unsigned int val;
101 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100102 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100103};
104
105/* proxy->options */
106static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
113 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100114 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
116 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
117 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100118 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100119 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
120 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100121 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
123 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100124#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100125 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100126#endif
127
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100128 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100129};
130
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100131/* proxy->options2 */
132static const struct cfg_opt cfg_opts2[] =
133{
134#ifdef CONFIG_HAP_LINUX_SPLICE
135 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
136 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
137 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
138#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200139 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
140 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200141 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
142 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200143 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200144 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200145 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200146 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200147 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148 { NULL, 0, 0, 0 }
149};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200150
Willy Tarreau6daf3432008-01-22 16:44:08 +0100151static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200152static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
153int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100154int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200156/* List head of all known configuration keywords */
157static struct cfg_kw_list cfg_keywords = {
158 .list = LIST_HEAD_INIT(cfg_keywords.list)
159};
160
Willy Tarreaubaaee002006-06-26 02:48:02 +0200161/*
162 * converts <str> to a list of listeners which are dynamically allocated.
163 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
164 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
165 * - <port> is a numerical port from 1 to 65535 ;
166 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
167 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200168 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200170static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171{
172 struct listener *l;
173 char *c, *next, *range, *dupstr;
174 int port, end;
175
176 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200177
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178 while (next && *next) {
179 struct sockaddr_storage ss;
180
181 str = next;
182 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100183 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184 *next++ = 0;
185 }
186
187 /* 2) look for the addr/port delimiter, it's the last colon. */
188 if ((range = strrchr(str, ':')) == NULL) {
189 Alert("Missing port number: '%s'\n", str);
190 goto fail;
191 }
192
193 *range++ = 0;
194
195 if (strrchr(str, ':') != NULL) {
196 /* IPv6 address contains ':' */
197 memset(&ss, 0, sizeof(ss));
198 ss.ss_family = AF_INET6;
199
200 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
201 Alert("Invalid server address: '%s'\n", str);
202 goto fail;
203 }
204 }
205 else {
206 memset(&ss, 0, sizeof(ss));
207 ss.ss_family = AF_INET;
208
209 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
210 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
211 }
212 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
213 struct hostent *he;
214
215 if ((he = gethostbyname(str)) == NULL) {
216 Alert("Invalid server name: '%s'\n", str);
217 goto fail;
218 }
219 else
220 ((struct sockaddr_in *)&ss)->sin_addr =
221 *(struct in_addr *) *(he->h_addr_list);
222 }
223 }
224
225 /* 3) look for the port-end delimiter */
226 if ((c = strchr(range, '-')) != NULL) {
227 *c++ = 0;
228 end = atol(c);
229 }
230 else {
231 end = atol(range);
232 }
233
234 port = atol(range);
235
236 if (port < 1 || port > 65535) {
237 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
238 goto fail;
239 }
240
241 if (end < 1 || end > 65535) {
242 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
243 goto fail;
244 }
245
246 for (; port <= end; port++) {
247 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200248 l->next = curproxy->listen;
249 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
251 l->fd = -1;
252 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100253 l->state = LI_INIT;
254
255 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 tcpv6_add_listener(l);
258 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100260 tcpv4_add_listener(l);
261 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200262
Willy Tarreaue6b98942007-10-29 01:09:36 +0100263 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 } /* end for(port) */
265 } /* end while(next) */
266 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200267 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 fail:
269 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200270 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271}
272
Willy Tarreau977b8e42006-12-29 14:19:17 +0100273/*
274 * Sends a warning if proxy <proxy> does not have at least one of the
275 * capabilities in <cap>. An optionnal <hint> may be added at the end
276 * of the warning to help the user. Returns 1 if a warning was emitted
277 * or 0 if the condition is valid.
278 */
279int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
280{
281 char *msg;
282
283 switch (cap) {
284 case PR_CAP_BE: msg = "no backend"; break;
285 case PR_CAP_FE: msg = "no frontend"; break;
286 case PR_CAP_RS: msg = "no ruleset"; break;
287 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
288 default: msg = "not enough"; break;
289 }
290
291 if (!(proxy->cap & cap)) {
292 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100293 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100294 return 1;
295 }
296 return 0;
297}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298
Willy Tarreau61d18892009-03-31 10:49:21 +0200299/* Report a warning if a rule is placed after a 'block' rule.
300 * Return 1 if the warning has been emitted, otherwise 0.
301 */
302int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
303{
304 if (!LIST_ISEMPTY(&proxy->block_cond)) {
305 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
306 file, line, arg);
307 return 1;
308 }
309 return 0;
310}
311
312/* Report a warning if a rule is placed after a reqrewrite rule.
313 * Return 1 if the warning has been emitted, otherwise 0.
314 */
315int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
316{
317 if (proxy->req_exp) {
318 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
319 file, line, arg);
320 return 1;
321 }
322 return 0;
323}
324
325/* Report a warning if a rule is placed after a reqadd rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
328int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
329{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100330 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a redirect rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
341int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
342{
343 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a 'use_backend' rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
354int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
355{
356 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* report a warning if a block rule is dangerously placed */
365int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
366{
367 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
368 warnif_rule_after_reqadd(proxy, file, line, arg) ||
369 warnif_rule_after_redirect(proxy, file, line, arg) ||
370 warnif_rule_after_use_backend(proxy, file, line, arg);
371}
372
373/* report a warning if a reqxxx rule is dangerously placed */
374int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
375{
376 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
377 warnif_rule_after_redirect(proxy, file, line, arg) ||
378 warnif_rule_after_use_backend(proxy, file, line, arg);
379}
380
381/* report a warning if a reqadd rule is dangerously placed */
382int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
383{
384 return warnif_rule_after_redirect(proxy, file, line, arg) ||
385 warnif_rule_after_use_backend(proxy, file, line, arg);
386}
387
Willy Tarreaubaaee002006-06-26 02:48:02 +0200388/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200389 * parse a line in a <global> section. Returns the error code, 0 if OK, or
390 * any combination of :
391 * - ERR_ABORT: must abort ASAP
392 * - ERR_FATAL: we can continue parsing but not start the service
393 * - ERR_WARN: a warning has been emitted
394 * - ERR_ALERT: an alert has been emitted
395 * Only the two first ones can stop processing, the two others are just
396 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200397 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200398int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200399{
Willy Tarreau058e9072009-07-20 09:30:05 +0200400 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401
402 if (!strcmp(args[0], "global")) { /* new section */
403 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200405 }
406 else if (!strcmp(args[0], "daemon")) {
407 global.mode |= MODE_DAEMON;
408 }
409 else if (!strcmp(args[0], "debug")) {
410 global.mode |= MODE_DEBUG;
411 }
412 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100413 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200414 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200415 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100416 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200417 }
418 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100419 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200421 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100422 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200423 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100424 else if (!strcmp(args[0], "nosplice")) {
425 global.tune.options &= ~GTUNE_USE_SPLICE;
426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427 else if (!strcmp(args[0], "quiet")) {
428 global.mode |= MODE_QUIET;
429 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200430 else if (!strcmp(args[0], "tune.maxpollevents")) {
431 if (global.tune.maxpollevents != 0) {
432 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200433 err_code |= ERR_ALERT;
434 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200435 }
436 if (*(args[1]) == 0) {
437 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200438 err_code |= ERR_ALERT | ERR_FATAL;
439 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200440 }
441 global.tune.maxpollevents = atol(args[1]);
442 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100443 else if (!strcmp(args[0], "tune.maxaccept")) {
444 if (global.tune.maxaccept != 0) {
445 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 err_code |= ERR_ALERT;
447 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100448 }
449 if (*(args[1]) == 0) {
450 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200451 err_code |= ERR_ALERT | ERR_FATAL;
452 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100453 }
454 global.tune.maxaccept = atol(args[1]);
455 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200456 else if (!strcmp(args[0], "tune.bufsize")) {
457 if (*(args[1]) == 0) {
458 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
459 err_code |= ERR_ALERT | ERR_FATAL;
460 goto out;
461 }
462 global.tune.bufsize = atol(args[1]);
463 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
464 global.tune.maxrewrite = global.tune.bufsize / 2;
465 }
466 else if (!strcmp(args[0], "tune.maxrewrite")) {
467 if (*(args[1]) == 0) {
468 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
469 err_code |= ERR_ALERT | ERR_FATAL;
470 goto out;
471 }
472 global.tune.maxrewrite = atol(args[1]);
473 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
474 global.tune.maxrewrite = global.tune.bufsize / 2;
475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 else if (!strcmp(args[0], "uid")) {
477 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200478 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200479 err_code |= ERR_ALERT;
480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 }
482 if (*(args[1]) == 0) {
483 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200484 err_code |= ERR_ALERT | ERR_FATAL;
485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 }
487 global.uid = atol(args[1]);
488 }
489 else if (!strcmp(args[0], "gid")) {
490 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200491 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT;
493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494 }
495 if (*(args[1]) == 0) {
496 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200497 err_code |= ERR_ALERT | ERR_FATAL;
498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
500 global.gid = atol(args[1]);
501 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200502 /* user/group name handling */
503 else if (!strcmp(args[0], "user")) {
504 struct passwd *ha_user;
505 if (global.uid != 0) {
506 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT;
508 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200509 }
510 errno = 0;
511 ha_user = getpwnam(args[1]);
512 if (ha_user != NULL) {
513 global.uid = (int)ha_user->pw_uid;
514 }
515 else {
516 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 +0200517 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200518 }
519 }
520 else if (!strcmp(args[0], "group")) {
521 struct group *ha_group;
522 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200523 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200524 err_code |= ERR_ALERT;
525 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200526 }
527 errno = 0;
528 ha_group = getgrnam(args[1]);
529 if (ha_group != NULL) {
530 global.gid = (int)ha_group->gr_gid;
531 }
532 else {
533 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 +0200534 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200535 }
536 }
537 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "nbproc")) {
539 if (global.nbproc != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200541 err_code |= ERR_ALERT;
542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
549 global.nbproc = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "maxconn")) {
552 if (global.maxconn != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200554 err_code |= ERR_ALERT;
555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200561 }
562 global.maxconn = atol(args[1]);
563#ifdef SYSTEM_MAXCONN
564 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
565 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);
566 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200567 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568 }
569#endif /* SYSTEM_MAXCONN */
570 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100571 else if (!strcmp(args[0], "maxpipes")) {
572 if (global.maxpipes != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200574 err_code |= ERR_ALERT;
575 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100581 }
582 global.maxpipes = atol(args[1]);
583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584 else if (!strcmp(args[0], "ulimit-n")) {
585 if (global.rlimit_nofile != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200587 err_code |= ERR_ALERT;
588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
595 global.rlimit_nofile = atol(args[1]);
596 }
597 else if (!strcmp(args[0], "chroot")) {
598 if (global.chroot != NULL) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200600 err_code |= ERR_ALERT;
601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 }
608 global.chroot = strdup(args[1]);
609 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200610 else if (!strcmp(args[0], "description")) {
611 int i, len=0;
612 char *d;
613
614 if (!*args[1]) {
615 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
616 file, linenum, args[0]);
617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
619 }
620
621 for(i=1; *args[i]; i++)
622 len += strlen(args[i])+1;
623
624 if (global.desc)
625 free(global.desc);
626
627 global.desc = d = (char *)calloc(1, len);
628
629 d += sprintf(d, "%s", args[1]);
630 for(i=2; *args[i]; i++)
631 d += sprintf(d, " %s", args[i]);
632 }
633 else if (!strcmp(args[0], "node")) {
634 int i;
635 char c;
636
637 for (i=0; args[1][i]; i++) {
638 c = args[1][i];
639 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
640 break;
641 }
642
643 if (!i || args[1][i]) {
644 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
645 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
646 file, linenum, args[0]);
647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
649 }
650
651 if (global.node)
652 free(global.node);
653
654 global.node = strdup(args[1]);
655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 else if (!strcmp(args[0], "pidfile")) {
657 if (global.pidfile != NULL) {
658 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT;
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
662 if (*(args[1]) == 0) {
663 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200664 err_code |= ERR_ALERT | ERR_FATAL;
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 }
667 global.pidfile = strdup(args[1]);
668 }
669 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100670 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200671 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672
673 if (*(args[1]) == 0 || *(args[2]) == 0) {
674 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 }
678
679 facility = get_log_facility(args[2]);
680 if (facility < 0) {
681 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
685
686 level = 7; /* max syslog level = debug */
687 if (*(args[3])) {
688 level = get_log_level(args[3]);
689 if (level < 0) {
690 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 }
695
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200696 minlvl = 0; /* limit syslog level to this level (emerg) */
697 if (*(args[4])) {
698 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200700 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200703 }
704 }
705
Robert Tsai81ae1952007-12-05 10:47:29 +0100706 if (args[1][0] == '/') {
707 logsrv.u.addr.sa_family = AF_UNIX;
708 logsrv.u.un = *str2sun(args[1]);
709 } else {
710 logsrv.u.addr.sa_family = AF_INET;
711 logsrv.u.in = *str2sa(args[1]);
712 if (!logsrv.u.in.sin_port)
713 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715
716 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100717 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 global.logfac1 = facility;
719 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200720 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100723 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 global.logfac2 = facility;
725 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200726 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 }
728 else {
729 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200732 }
733 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
734 if (global.spread_checks != 0) {
735 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT;
737 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200738 }
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200743 }
744 global.spread_checks = atol(args[1]);
745 if (global.spread_checks < 0 || global.spread_checks > 50) {
746 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200751 struct cfg_kw_list *kwl;
752 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200753 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200754
755 list_for_each_entry(kwl, &cfg_keywords.list, list) {
756 for (index = 0; kwl->kw[index].kw != NULL; index++) {
757 if (kwl->kw[index].section != CFG_GLOBAL)
758 continue;
759 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
760 /* prepare error message just in case */
761 snprintf(trash, sizeof(trash),
762 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200763 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
764 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200765 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200767 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200768 else if (rc > 0) {
769 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_WARN;
771 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200772 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200774 }
775 }
776 }
777
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200781
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 out:
783 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784}
785
Willy Tarreau97cb7802010-01-03 20:23:58 +0100786/* Perform the most basic initialization of a proxy :
787 * memset(), list_init(*), reset_timeouts(*).
788 */
789static void init_new_proxy(struct proxy *p)
790{
791 memset(p, 0, sizeof(struct proxy));
792 LIST_INIT(&p->pendconns);
793 LIST_INIT(&p->acl);
794 LIST_INIT(&p->block_cond);
795 LIST_INIT(&p->redirect_rules);
796 LIST_INIT(&p->mon_fail_cond);
797 LIST_INIT(&p->switching_rules);
798 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100799 LIST_INIT(&p->req_add);
800 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100801
802 /* Timeouts are defined as -1 */
803 proxy_reset_timeouts(p);
804}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200806void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100808 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 defproxy.mode = PR_MODE_TCP;
810 defproxy.state = PR_STNEW;
811 defproxy.maxconn = cfg_maxpconn;
812 defproxy.conn_retries = CONN_RETRIES;
813 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100814
815 defproxy.defsrv.inter = DEF_CHKINTR;
816 defproxy.defsrv.fastinter = 0;
817 defproxy.defsrv.downinter = 0;
818 defproxy.defsrv.rise = DEF_RISETIME;
819 defproxy.defsrv.fall = DEF_FALLTIME;
820 defproxy.defsrv.check_port = 0;
821 defproxy.defsrv.maxqueue = 0;
822 defproxy.defsrv.minconn = 0;
823 defproxy.defsrv.maxconn = 0;
824 defproxy.defsrv.slowstart = 0;
825 defproxy.defsrv.onerror = DEF_HANA_ONERR;
826 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
827 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828}
829
830/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100831 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200832 * Returns the error code, 0 if OK, or any combination of :
833 * - ERR_ABORT: must abort ASAP
834 * - ERR_FATAL: we can continue parsing but not start the service
835 * - ERR_WARN: a warning has been emitted
836 * - ERR_ALERT: an alert has been emitted
837 * Only the two first ones can stop processing, the two others are just
838 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200840int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841{
842 static struct proxy *curproxy = NULL;
843 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200844 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100845 int rc;
846 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200847 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848
Willy Tarreau977b8e42006-12-29 14:19:17 +0100849 if (!strcmp(args[0], "listen"))
850 rc = PR_CAP_LISTEN;
851 else if (!strcmp(args[0], "frontend"))
852 rc = PR_CAP_FE | PR_CAP_RS;
853 else if (!strcmp(args[0], "backend"))
854 rc = PR_CAP_BE | PR_CAP_RS;
855 else if (!strcmp(args[0], "ruleset"))
856 rc = PR_CAP_RS;
857 else
858 rc = PR_CAP_NONE;
859
860 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 if (!*args[1]) {
862 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
863 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
864 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200865 err_code |= ERR_ALERT | ERR_ABORT;
866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200868
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100869 err = invalid_char(args[1]);
870 if (err) {
871 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
872 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200873 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100874 }
875
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200876 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
877 /*
878 * If there are two proxies with the same name only following
879 * combinations are allowed:
880 *
881 * listen backend frontend ruleset
882 * listen - - - -
883 * backend - - OK -
884 * frontend - OK - -
885 * ruleset - - - -
886 */
887
888 if (!strcmp(curproxy->id, args[1]) &&
889 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
890 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200891 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
892 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
893 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200894 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200895 }
896 }
897
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
899 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200900 err_code |= ERR_ALERT | ERR_ABORT;
901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100903
Willy Tarreau97cb7802010-01-03 20:23:58 +0100904 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 curproxy->next = proxy;
906 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200907 curproxy->conf.file = file;
908 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200909 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100911 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912
913 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100914 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200915 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200916 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200917 err_code |= ERR_FATAL;
918 goto out;
919 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200920 new = curproxy->listen;
921 while (new != last) {
922 new->conf.file = file;
923 new->conf.line = linenum;
924 new = new->next;
925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 global.maxsock++;
927 }
928
929 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100930 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
931
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100934 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200935 curproxy->no_options = defproxy.no_options;
936 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100937 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100938 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200939 curproxy->except_net = defproxy.except_net;
940 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200941 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200942 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200944 if (defproxy.fwdfor_hdr_len) {
945 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
946 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
947 }
948
Willy Tarreaub86db342009-11-30 11:50:16 +0100949 if (defproxy.orgto_hdr_len) {
950 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
951 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
952 }
953
Willy Tarreau977b8e42006-12-29 14:19:17 +0100954 if (curproxy->cap & PR_CAP_FE) {
955 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100956 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200957 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100958
959 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200960 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
961 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100962
963 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
964 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965
Willy Tarreau977b8e42006-12-29 14:19:17 +0100966 if (curproxy->cap & PR_CAP_BE) {
967 curproxy->fullconn = defproxy.fullconn;
968 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969
Willy Tarreau977b8e42006-12-29 14:19:17 +0100970 if (defproxy.check_req)
971 curproxy->check_req = strdup(defproxy.check_req);
972 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973
Willy Tarreau977b8e42006-12-29 14:19:17 +0100974 if (defproxy.cookie_name)
975 curproxy->cookie_name = strdup(defproxy.cookie_name);
976 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +0100977 if (defproxy.cookie_domain)
978 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +0100979
Emeric Brun647caf12009-06-30 17:57:00 +0200980 if (defproxy.rdp_cookie_name)
981 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
982 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
983
Willy Tarreau01732802007-11-01 22:48:15 +0100984 if (defproxy.url_param_name)
985 curproxy->url_param_name = strdup(defproxy.url_param_name);
986 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100987
Benoitaffb4812009-03-25 13:02:10 +0100988 if (defproxy.hh_name)
989 curproxy->hh_name = strdup(defproxy.hh_name);
990 curproxy->hh_len = defproxy.hh_len;
991 curproxy->hh_match_domain = defproxy.hh_match_domain;
992
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100993 if (defproxy.iface_name)
994 curproxy->iface_name = strdup(defproxy.iface_name);
995 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200998 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100999 if (defproxy.capture_name)
1000 curproxy->capture_name = strdup(defproxy.capture_name);
1001 curproxy->capture_namelen = defproxy.capture_namelen;
1002 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004
Willy Tarreau977b8e42006-12-29 14:19:17 +01001005 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001006 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001007 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001008 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001009 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001010 curproxy->uri_auth = defproxy.uri_auth;
1011 curproxy->mon_net = defproxy.mon_net;
1012 curproxy->mon_mask = defproxy.mon_mask;
1013 if (defproxy.monitor_uri)
1014 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1015 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001016 if (defproxy.defbe.name)
1017 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001018 }
1019
1020 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001021 curproxy->timeout.connect = defproxy.timeout.connect;
1022 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001023 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001024 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001025 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001026 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001027 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001028 curproxy->source_addr = defproxy.source_addr;
1029 }
1030
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 curproxy->mode = defproxy.mode;
1032 curproxy->logfac1 = defproxy.logfac1;
1033 curproxy->logsrv1 = defproxy.logsrv1;
1034 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001035 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 curproxy->logfac2 = defproxy.logfac2;
1037 curproxy->logsrv2 = defproxy.logsrv2;
1038 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001039 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001041 curproxy->conf.used_listener_id = EB_ROOT;
1042 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001043
Willy Tarreau93893792009-07-23 13:19:11 +02001044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 }
1046 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1047 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001048 /* FIXME-20070101: we should do this too at the end of the
1049 * config parsing to free all default values.
1050 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001051 free(defproxy.check_req);
1052 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001053 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001054 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001055 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001056 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001057 free(defproxy.capture_name);
1058 free(defproxy.monitor_uri);
1059 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001060 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001061 free(defproxy.fwdfor_hdr_name);
1062 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001063 free(defproxy.orgto_hdr_name);
1064 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001065
Willy Tarreaua534fea2008-08-03 12:19:50 +02001066 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001067 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001068
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 /* we cannot free uri_auth because it might already be used */
1070 init_default_instance();
1071 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001072 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 }
1075 else if (curproxy == NULL) {
1076 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 }
1080
Willy Tarreau977b8e42006-12-29 14:19:17 +01001081
1082 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001084 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001085 int cur_arg;
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 if (curproxy == &defproxy) {
1088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001092 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001093 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094
1095 if (strchr(args[1], ':') == NULL) {
1096 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1097 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001101
1102 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001103 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001107
Willy Tarreau90a570f2009-10-04 20:54:54 +02001108 new_listen = curproxy->listen;
1109 while (new_listen != last_listen) {
1110 new_listen->conf.file = file;
1111 new_listen->conf.line = linenum;
1112 new_listen = new_listen->next;
1113 }
1114
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001115 cur_arg = 2;
1116 while (*(args[cur_arg])) {
1117 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1118#ifdef SO_BINDTODEVICE
1119 struct listener *l;
1120
1121 if (!*args[cur_arg + 1]) {
1122 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001126 }
1127
1128 for (l = curproxy->listen; l != last_listen; l = l->next)
1129 l->interface = strdup(args[cur_arg + 1]);
1130
1131 global.last_checks |= LSTCHK_NETADM;
1132
1133 cur_arg += 2;
1134 continue;
1135#else
1136 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1137 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001140#endif
1141 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001142 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1143#ifdef TCP_MAXSEG
1144 struct listener *l;
1145 int mss;
1146
1147 if (!*args[cur_arg + 1]) {
1148 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1149 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001152 }
1153
1154 mss = str2uic(args[cur_arg + 1]);
1155 if (mss < 1 || mss > 65535) {
1156 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1157 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001160 }
1161
1162 for (l = curproxy->listen; l != last_listen; l = l->next)
1163 l->maxseg = mss;
1164
1165 cur_arg += 2;
1166 continue;
1167#else
1168 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1169 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001172#endif
1173 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001174
1175 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1176#ifdef TCP_DEFER_ACCEPT
1177 struct listener *l;
1178
1179 for (l = curproxy->listen; l != last_listen; l = l->next)
1180 l->options |= LI_O_DEF_ACCEPT;
1181
1182 cur_arg ++;
1183 continue;
1184#else
1185 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1186 file, linenum, args[0], args[cur_arg]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189#endif
1190 }
1191
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001192 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001193#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001194 struct listener *l;
1195
1196 for (l = curproxy->listen; l != last_listen; l = l->next)
1197 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001198
1199 cur_arg ++;
1200 continue;
1201#else
1202 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1203 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001206#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001207 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001208
1209 if (!strcmp(args[cur_arg], "name")) {
1210 struct listener *l;
1211
1212 for (l = curproxy->listen; l != last_listen; l = l->next)
1213 l->name = strdup(args[cur_arg + 1]);
1214
1215 cur_arg += 2;
1216 continue;
1217 }
1218
1219 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001220 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001221 struct listener *l;
1222
1223 if (curproxy->listen->next != last_listen) {
1224 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1225 file, linenum, args[cur_arg]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 if (!*args[cur_arg + 1]) {
1231 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1232 file, linenum, args[cur_arg]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236
1237 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001238 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001239
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001240 if (curproxy->listen->luid <= 0) {
1241 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001242 file, linenum);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001247 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1248 if (node) {
1249 l = container_of(node, struct listener, conf.id);
1250 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1251 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1252 err_code |= ERR_ALERT | ERR_FATAL;
1253 goto out;
1254 }
1255 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1256
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001257 cur_arg += 2;
1258 continue;
1259 }
1260
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001261 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 }
1269 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1270 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1271 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1272 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001276 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001277 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001278
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 /* flush useless bits */
1280 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001283 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001284 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001285 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001286
Willy Tarreau1c47f852006-07-09 08:22:27 +02001287 if (!*args[1]) {
1288 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001292 }
1293
Willy Tarreaua534fea2008-08-03 12:19:50 +02001294 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001295 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001296 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001297 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001298 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1299
Willy Tarreau93893792009-07-23 13:19:11 +02001300 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1303 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1304 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1305 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1306 else {
1307 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
1311 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001312 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001313 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001314
1315 if (curproxy == &defproxy) {
1316 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001320 }
1321
1322 if (!*args[1]) {
1323 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1324 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001327 }
1328
1329 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001330 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001331
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001332 if (curproxy->uuid <= 0) {
1333 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001334 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001337 }
1338
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001339 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1340 if (node) {
1341 struct proxy *target = container_of(node, struct proxy, conf.id);
1342 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1343 file, linenum, proxy_type_str(curproxy), curproxy->id,
1344 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
1347 }
1348 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001349 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001350 else if (!strcmp(args[0], "description")) {
1351 int i, len=0;
1352 char *d;
1353
1354 if (!*args[1]) {
1355 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1356 file, linenum, args[0]);
1357 return -1;
1358 }
1359
1360 for(i=1; *args[i]; i++)
1361 len += strlen(args[i])+1;
1362
1363 d = (char *)calloc(1, len);
1364 curproxy->desc = d;
1365
1366 d += sprintf(d, "%s", args[1]);
1367 for(i=2; *args[i]; i++)
1368 d += sprintf(d, " %s", args[i]);
1369
1370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1372 curproxy->state = PR_STSTOPPED;
1373 }
1374 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1375 curproxy->state = PR_STNEW;
1376 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001377 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1378 int cur_arg = 1;
1379 unsigned int set = 0;
1380
1381 while (*args[cur_arg]) {
1382 int u;
1383 if (strcmp(args[cur_arg], "all") == 0) {
1384 set = 0;
1385 break;
1386 }
1387 else if (strcmp(args[cur_arg], "odd") == 0) {
1388 set |= 0x55555555;
1389 }
1390 else if (strcmp(args[cur_arg], "even") == 0) {
1391 set |= 0xAAAAAAAA;
1392 }
1393 else {
1394 u = str2uic(args[cur_arg]);
1395 if (u < 1 || u > 32) {
1396 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001400 }
1401 if (u > global.nbproc) {
1402 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001404 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001405 }
1406 set |= 1 << (u - 1);
1407 }
1408 cur_arg++;
1409 }
1410 curproxy->bind_proc = set;
1411 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001412 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001413 if (curproxy == &defproxy) {
1414 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001417 }
1418
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001419 err = invalid_char(args[1]);
1420 if (err) {
1421 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1422 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001423 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001424 }
1425
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001426 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1427 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1428 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001431 }
1432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1434 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435
Willy Tarreau977b8e42006-12-29 14:19:17 +01001436 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001437 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001438
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 if (*(args[1]) == 0) {
1440 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1441 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001442 err_code |= ERR_ALERT | ERR_FATAL;
1443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001445
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001446 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001447 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 curproxy->cookie_name = strdup(args[1]);
1449 curproxy->cookie_len = strlen(curproxy->cookie_name);
1450
1451 cur_arg = 2;
1452 while (*(args[cur_arg])) {
1453 if (!strcmp(args[cur_arg], "rewrite")) {
1454 curproxy->options |= PR_O_COOK_RW;
1455 }
1456 else if (!strcmp(args[cur_arg], "indirect")) {
1457 curproxy->options |= PR_O_COOK_IND;
1458 }
1459 else if (!strcmp(args[cur_arg], "insert")) {
1460 curproxy->options |= PR_O_COOK_INS;
1461 }
1462 else if (!strcmp(args[cur_arg], "nocache")) {
1463 curproxy->options |= PR_O_COOK_NOC;
1464 }
1465 else if (!strcmp(args[cur_arg], "postonly")) {
1466 curproxy->options |= PR_O_COOK_POST;
1467 }
1468 else if (!strcmp(args[cur_arg], "prefix")) {
1469 curproxy->options |= PR_O_COOK_PFX;
1470 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001471 else if (!strcmp(args[cur_arg], "domain")) {
1472 if (!*args[cur_arg + 1]) {
1473 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1474 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001477 }
1478
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001479 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001480 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001481 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1482 " dots nor does not start with a dot."
1483 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001484 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001485 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001486 }
1487
1488 err = invalid_domainchar(args[cur_arg + 1]);
1489 if (err) {
1490 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1491 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001492 err_code |= ERR_ALERT | ERR_FATAL;
1493 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001494 }
1495
Willy Tarreau68a897b2009-12-03 23:28:34 +01001496 if (!curproxy->cookie_domain) {
1497 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1498 } else {
1499 /* one domain was already specified, add another one by
1500 * building the string which will be returned along with
1501 * the cookie.
1502 */
1503 char *new_ptr;
1504 int new_len = strlen(curproxy->cookie_domain) +
1505 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1506 new_ptr = malloc(new_len);
1507 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1508 free(curproxy->cookie_domain);
1509 curproxy->cookie_domain = new_ptr;
1510 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001511 cur_arg++;
1512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001514 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 }
1519 cur_arg++;
1520 }
1521 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1522 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001524 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001525 }
1526
1527 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1528 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1529 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001530 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 }
1532 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001533 else if (!strcmp(args[0], "persist")) { /* persist */
1534 if (*(args[1]) == 0) {
1535 Alert("parsing [%s:%d] : missing persist method.\n",
1536 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001539 }
1540
1541 if (!strncmp(args[1], "rdp-cookie", 10)) {
1542 curproxy->options2 |= PR_O2_RDPC_PRST;
1543
1544 if (*(args[1] + 10 ) == '(') { /* cookie name */
1545 const char *beg, *end;
1546
1547 beg = args[1] + 11;
1548 end = strchr(beg, ')');
1549
1550 if (!end || end == beg) {
1551 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1552 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001553 err_code |= ERR_ALERT | ERR_FATAL;
1554 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001555 }
1556
1557 free(curproxy->rdp_cookie_name);
1558 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1559 curproxy->rdp_cookie_len = end-beg;
1560 }
1561 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1562 free(curproxy->rdp_cookie_name);
1563 curproxy->rdp_cookie_name = strdup("msts");
1564 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1565 }
1566 else { /* syntax */
1567 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1568 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001571 }
1572 }
1573 else {
1574 Alert("parsing [%s:%d] : unknown persist method.\n",
1575 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001578 }
1579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001581 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001583 if (curproxy == &defproxy) {
1584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
1587 }
1588
Willy Tarreau977b8e42006-12-29 14:19:17 +01001589 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001590 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001591
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001593 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 }
1598 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001599 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 curproxy->appsession_name = strdup(args[1]);
1601 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1602 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001603 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1604 if (err) {
1605 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1606 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001609 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001610 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001611
Willy Tarreau51041c72007-09-09 21:56:53 +02001612 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1613 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001614 err_code |= ERR_ALERT | ERR_ABORT;
1615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001617
1618 cur_arg = 6;
1619 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001620 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1621 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001622 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001623 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001624 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001625 } else if (!strcmp(args[cur_arg], "prefix")) {
1626 curproxy->options2 |= PR_O2_AS_PFX;
1627 } else if (!strcmp(args[cur_arg], "mode")) {
1628 if (!*args[cur_arg + 1]) {
1629 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1630 file, linenum, args[0], args[cur_arg]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
1634
1635 cur_arg++;
1636 if (!strcmp(args[cur_arg], "query-string")) {
1637 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1638 curproxy->options2 |= PR_O2_AS_M_QS;
1639 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1640 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1641 curproxy->options2 |= PR_O2_AS_M_PP;
1642 } else {
1643 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1644 err_code |= ERR_ALERT | ERR_FATAL;
1645 goto out;
1646 }
1647 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001648 cur_arg++;
1649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 } /* Url App Session */
1651 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001652 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001654
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 if (*(args[4]) == 0) {
1657 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001662 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001663 curproxy->capture_name = strdup(args[2]);
1664 curproxy->capture_namelen = strlen(curproxy->capture_name);
1665 curproxy->capture_len = atol(args[4]);
1666 if (curproxy->capture_len >= CAPTURE_LEN) {
1667 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1668 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001669 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 curproxy->capture_len = CAPTURE_LEN - 1;
1671 }
1672 curproxy->to_log |= LW_COOKIE;
1673 }
1674 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1675 struct cap_hdr *hdr;
1676
1677 if (curproxy == &defproxy) {
1678 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 +02001679 err_code |= ERR_ALERT | ERR_FATAL;
1680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001681 }
1682
1683 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1684 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1685 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 }
1689
1690 hdr = calloc(sizeof(struct cap_hdr), 1);
1691 hdr->next = curproxy->req_cap;
1692 hdr->name = strdup(args[3]);
1693 hdr->namelen = strlen(args[3]);
1694 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001695 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 hdr->index = curproxy->nb_req_cap++;
1697 curproxy->req_cap = hdr;
1698 curproxy->to_log |= LW_REQHDR;
1699 }
1700 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1701 struct cap_hdr *hdr;
1702
1703 if (curproxy == &defproxy) {
1704 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 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
1706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 }
1708
1709 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1710 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1711 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 }
1715 hdr = calloc(sizeof(struct cap_hdr), 1);
1716 hdr->next = curproxy->rsp_cap;
1717 hdr->name = strdup(args[3]);
1718 hdr->namelen = strlen(args[3]);
1719 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001720 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 hdr->index = curproxy->nb_rsp_cap++;
1722 curproxy->rsp_cap = hdr;
1723 curproxy->to_log |= LW_RSPHDR;
1724 }
1725 else {
1726 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1727 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730 }
1731 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001734 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 if (*(args[1]) == 0) {
1737 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1738 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001739 err_code |= ERR_ALERT | ERR_FATAL;
1740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 }
1742 curproxy->conn_retries = atol(args[1]);
1743 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001744 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1745 int pol = ACL_COND_NONE;
1746 struct acl_cond *cond;
1747
Willy Tarreaub099aca2008-10-12 17:26:37 +02001748 if (curproxy == &defproxy) {
1749 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001752 }
1753
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001754 if (!strcmp(args[1], "if"))
1755 pol = ACL_COND_IF;
1756 else if (!strcmp(args[1], "unless"))
1757 pol = ACL_COND_UNLESS;
1758
1759 if (pol == ACL_COND_NONE) {
1760 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001764 }
1765
1766 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1767 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1768 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001771 }
Willy Tarreau88922352009-10-04 22:02:50 +02001772 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001773 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001774 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001775 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001776 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001777 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001778 else if (!strcmp(args[0], "redirect")) {
1779 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001780 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001781 struct redirect_rule *rule;
1782 int cur_arg;
1783 int type = REDIRECT_TYPE_NONE;
1784 int code = 302;
1785 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001786 char *cookie = NULL;
1787 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001788 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001789
1790 cur_arg = 1;
1791 while (*(args[cur_arg])) {
1792 if (!strcmp(args[cur_arg], "location")) {
1793 if (!*args[cur_arg + 1]) {
1794 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1795 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001798 }
1799
1800 type = REDIRECT_TYPE_LOCATION;
1801 cur_arg++;
1802 destination = args[cur_arg];
1803 }
1804 else if (!strcmp(args[cur_arg], "prefix")) {
1805 if (!*args[cur_arg + 1]) {
1806 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1807 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001810 }
1811
1812 type = REDIRECT_TYPE_PREFIX;
1813 cur_arg++;
1814 destination = args[cur_arg];
1815 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001816 else if (!strcmp(args[cur_arg], "set-cookie")) {
1817 if (!*args[cur_arg + 1]) {
1818 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1819 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001822 }
1823
1824 cur_arg++;
1825 cookie = args[cur_arg];
1826 cookie_set = 1;
1827 }
1828 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1829 if (!*args[cur_arg + 1]) {
1830 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1831 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001834 }
1835
1836 cur_arg++;
1837 cookie = args[cur_arg];
1838 cookie_set = 0;
1839 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001840 else if (!strcmp(args[cur_arg],"code")) {
1841 if (!*args[cur_arg + 1]) {
1842 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1843 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001846 }
1847 cur_arg++;
1848 code = atol(args[cur_arg]);
1849 if (code < 301 || code > 303) {
1850 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1851 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001854 }
1855 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001856 else if (!strcmp(args[cur_arg],"drop-query")) {
1857 flags |= REDIRECT_FLAG_DROP_QS;
1858 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001859 else if (!strcmp(args[cur_arg],"append-slash")) {
1860 flags |= REDIRECT_FLAG_APPEND_SLASH;
1861 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001862 else if (!strcmp(args[cur_arg], "if")) {
1863 pol = ACL_COND_IF;
1864 cur_arg++;
1865 break;
1866 }
1867 else if (!strcmp(args[cur_arg], "unless")) {
1868 pol = ACL_COND_UNLESS;
1869 cur_arg++;
1870 break;
1871 }
1872 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001873 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001874 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001877 }
1878 cur_arg++;
1879 }
1880
1881 if (type == REDIRECT_TYPE_NONE) {
1882 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1883 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001886 }
1887
Willy Tarreauf285f542010-01-03 20:03:03 +01001888 if (pol != ACL_COND_NONE &&
1889 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001890 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001891 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001894 }
1895
Willy Tarreauf285f542010-01-03 20:03:03 +01001896 if (cond) {
1897 cond->file = file;
1898 cond->line = linenum;
1899 curproxy->acl_requires |= cond->requires;
1900 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001901 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1902 rule->cond = cond;
1903 rule->rdr_str = strdup(destination);
1904 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001905 if (cookie) {
1906 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1907 * a clear consists in appending "; Max-Age=0" at the end.
1908 */
1909 rule->cookie_len = strlen(cookie);
1910 if (cookie_set)
1911 rule->cookie_str = strdup(cookie);
1912 else {
1913 rule->cookie_str = malloc(rule->cookie_len + 12);
1914 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1915 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1916 rule->cookie_len += 11;
1917 }
1918 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001919 rule->type = type;
1920 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001921 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001922 LIST_INIT(&rule->list);
1923 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001924 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001925 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001926 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001927 int pol = ACL_COND_NONE;
1928 struct acl_cond *cond;
1929 struct switching_rule *rule;
1930
Willy Tarreaub099aca2008-10-12 17:26:37 +02001931 if (curproxy == &defproxy) {
1932 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001935 }
1936
Willy Tarreau55ea7572007-06-17 19:56:27 +02001937 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001939
1940 if (*(args[1]) == 0) {
1941 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001944 }
1945
1946 if (!strcmp(args[2], "if"))
1947 pol = ACL_COND_IF;
1948 else if (!strcmp(args[2], "unless"))
1949 pol = ACL_COND_UNLESS;
1950
1951 if (pol == ACL_COND_NONE) {
1952 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_ALERT | ERR_FATAL;
1955 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001956 }
1957
1958 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001959 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001960 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001963 }
1964
Willy Tarreau88922352009-10-04 22:02:50 +02001965 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001966 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001967 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001968 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001969 struct acl *acl;
1970 const char *name;
1971
1972 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1973 name = acl ? acl->name : "(unknown)";
1974 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1975 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001977 }
1978
Willy Tarreau55ea7572007-06-17 19:56:27 +02001979 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1980 rule->cond = cond;
1981 rule->be.name = strdup(args[1]);
1982 LIST_INIT(&rule->list);
1983 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1990 curproxy->uri_auth = NULL; /* we must detach from the default config */
1991
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01001992 if (!*args[1]) {
1993 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 } else if (!strcmp(args[1], "uri")) {
1995 if (*(args[2]) == 0) {
1996 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2000 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_ALERT | ERR_ABORT;
2002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 }
2004 } else if (!strcmp(args[1], "realm")) {
2005 if (*(args[2]) == 0) {
2006 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2010 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_ALERT | ERR_ABORT;
2012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002014 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002015 unsigned interval;
2016
2017 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2018 if (err) {
2019 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2020 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002023 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2024 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002025 err_code |= ERR_ALERT | ERR_ABORT;
2026 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 } else if (!strcmp(args[1], "auth")) {
2029 if (*(args[2]) == 0) {
2030 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2034 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_ALERT | ERR_ABORT;
2036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 }
2038 } else if (!strcmp(args[1], "scope")) {
2039 if (*(args[2]) == 0) {
2040 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2044 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_ABORT;
2046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047 }
2048 } else if (!strcmp(args[1], "enable")) {
2049 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_ALERT | ERR_ABORT;
2052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002054 } else if (!strcmp(args[1], "hide-version")) {
2055 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2056 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_ABORT;
2058 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002059 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002060 } else if (!strcmp(args[1], "show-legends")) {
2061 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2062 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2063 err_code |= ERR_ALERT | ERR_ABORT;
2064 goto out;
2065 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002066 } else if (!strcmp(args[1], "show-node")) {
2067
2068 if (*args[2]) {
2069 int i;
2070 char c;
2071
2072 for (i=0; args[2][i]; i++) {
2073 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002074 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002075 break;
2076 }
2077
2078 if (!i || args[2][i]) {
2079 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2080 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2081 file, linenum, args[0], args[1]);
2082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
2084 }
2085 }
2086
2087 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2088 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2089 err_code |= ERR_ALERT | ERR_ABORT;
2090 goto out;
2091 }
2092 } else if (!strcmp(args[1], "show-desc")) {
2093 char *desc = NULL;
2094
2095 if (*args[2]) {
2096 int i, len=0;
2097 char *d;
2098
2099 for(i=2; *args[i]; i++)
2100 len += strlen(args[i])+1;
2101
2102 desc = d = (char *)calloc(1, len);
2103
2104 d += sprintf(d, "%s", args[2]);
2105 for(i=3; *args[i]; i++)
2106 d += sprintf(d, " %s", args[i]);
2107 }
2108
2109 if (!*args[2] && !global.desc)
2110 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2111 file, linenum, args[1]);
2112 else {
2113 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2114 free(desc);
2115 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2116 err_code |= ERR_ALERT | ERR_ABORT;
2117 goto out;
2118 }
2119 free(desc);
2120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002122stats_error_parsing:
2123 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2124 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002125 err_code |= ERR_ALERT | ERR_FATAL;
2126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 }
2128 }
2129 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002130 int optnum;
2131
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002132 if (*(args[1]) == '\0') {
2133 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2134 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002138
2139 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2140 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002141 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2142 err_code |= ERR_WARN;
2143 goto out;
2144 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002145
Willy Tarreau3842f002009-06-14 11:39:52 +02002146 curproxy->no_options &= ~cfg_opts[optnum].val;
2147 curproxy->options &= ~cfg_opts[optnum].val;
2148
2149 switch (kwm) {
2150 case KWM_STD:
2151 curproxy->options |= cfg_opts[optnum].val;
2152 break;
2153 case KWM_NO:
2154 curproxy->no_options |= cfg_opts[optnum].val;
2155 break;
2156 case KWM_DEF: /* already cleared */
2157 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002158 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002159
Willy Tarreau93893792009-07-23 13:19:11 +02002160 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002161 }
2162 }
2163
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002164 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2165 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002166 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2167 err_code |= ERR_WARN;
2168 goto out;
2169 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002170
Willy Tarreau3842f002009-06-14 11:39:52 +02002171 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2172 curproxy->options2 &= ~cfg_opts2[optnum].val;
2173
2174 switch (kwm) {
2175 case KWM_STD:
2176 curproxy->options2 |= cfg_opts2[optnum].val;
2177 break;
2178 case KWM_NO:
2179 curproxy->no_options2 |= cfg_opts2[optnum].val;
2180 break;
2181 case KWM_DEF: /* already cleared */
2182 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002183 }
Willy Tarreau93893792009-07-23 13:19:11 +02002184 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002185 }
2186 }
2187
Willy Tarreau3842f002009-06-14 11:39:52 +02002188 if (kwm != KWM_STD) {
2189 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002190 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002193 }
2194
Emeric Brun3a058f32009-06-30 18:26:00 +02002195 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002197 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002199 if (*(args[2]) != '\0') {
2200 if (!strcmp(args[2], "clf")) {
2201 curproxy->options2 |= PR_O2_CLFLOG;
2202 } else {
2203 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002206 }
2207 }
2208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 else if (!strcmp(args[1], "tcplog"))
2210 /* generate a detailed TCP log */
2211 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212 else if (!strcmp(args[1], "tcpka")) {
2213 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002214 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002216
2217 if (curproxy->cap & PR_CAP_FE)
2218 curproxy->options |= PR_O_TCP_CLI_KA;
2219 if (curproxy->cap & PR_CAP_BE)
2220 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221 }
2222 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002223 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_WARN;
2225
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002227 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002228 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002229 curproxy->options &= ~PR_O_SMTP_CHK;
2230 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 if (!*args[2]) { /* no argument */
2232 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2233 curproxy->check_len = strlen(DEF_CHECK_REQ);
2234 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002235 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 curproxy->check_req = (char *)malloc(reqlen);
2237 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2238 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2239 } else { /* more arguments : METHOD URI [HTTP_VER] */
2240 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2241 if (*args[4])
2242 reqlen += strlen(args[4]);
2243 else
2244 reqlen += strlen("HTTP/1.0");
2245
2246 curproxy->check_req = (char *)malloc(reqlen);
2247 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2248 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2249 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002250 }
2251 else if (!strcmp(args[1], "ssl-hello-chk")) {
2252 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002253 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002255
Willy Tarreaua534fea2008-08-03 12:19:50 +02002256 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002257 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002258 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002259 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
Willy Tarreau23677902007-05-08 23:50:35 +02002261 else if (!strcmp(args[1], "smtpchk")) {
2262 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002263 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002264 curproxy->options &= ~PR_O_HTTP_CHK;
2265 curproxy->options &= ~PR_O_SSL3_CHK;
2266 curproxy->options |= PR_O_SMTP_CHK;
2267
2268 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2269 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2270 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2271 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2272 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2273 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2274 curproxy->check_req = (char *)malloc(reqlen);
2275 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2276 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2277 } else {
2278 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2279 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2280 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2281 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2282 }
2283 }
2284 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002285 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002286 int cur_arg;
2287
2288 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2289 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002290 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002291
2292 curproxy->options |= PR_O_FWDFOR;
2293
2294 free(curproxy->fwdfor_hdr_name);
2295 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2296 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2297
2298 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2299 cur_arg = 2;
2300 while (*(args[cur_arg])) {
2301 if (!strcmp(args[cur_arg], "except")) {
2302 /* suboption except - needs additional argument for it */
2303 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2304 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2305 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002308 }
2309 /* flush useless bits */
2310 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002311 cur_arg += 2;
2312 } else if (!strcmp(args[cur_arg], "header")) {
2313 /* suboption header - needs additional argument for it */
2314 if (*(args[cur_arg+1]) == 0) {
2315 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2316 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002319 }
2320 free(curproxy->fwdfor_hdr_name);
2321 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2322 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2323 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002324 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002325 /* unknown suboption - catchall */
2326 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2327 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002330 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002331 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002332 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002333 else if (!strcmp(args[1], "originalto")) {
2334 int cur_arg;
2335
2336 /* insert x-original-to field, but not for the IP address listed as an except.
2337 * set default options (ie: bitfield, header name, etc)
2338 */
2339
2340 curproxy->options |= PR_O_ORGTO;
2341
2342 free(curproxy->orgto_hdr_name);
2343 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2344 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2345
2346 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2347 cur_arg = 2;
2348 while (*(args[cur_arg])) {
2349 if (!strcmp(args[cur_arg], "except")) {
2350 /* suboption except - needs additional argument for it */
2351 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2352 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2353 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002356 }
2357 /* flush useless bits */
2358 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2359 cur_arg += 2;
2360 } else if (!strcmp(args[cur_arg], "header")) {
2361 /* suboption header - needs additional argument for it */
2362 if (*(args[cur_arg+1]) == 0) {
2363 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2364 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002367 }
2368 free(curproxy->orgto_hdr_name);
2369 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2370 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2371 cur_arg += 2;
2372 } else {
2373 /* unknown suboption - catchall */
2374 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2375 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002378 }
2379 } /* end while loop */
2380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 else {
2382 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 }
Willy Tarreau93893792009-07-23 13:19:11 +02002386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002388 else if (!strcmp(args[0], "default_backend")) {
2389 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002391
2392 if (*(args[1]) == 0) {
2393 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002396 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002397 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002398 curproxy->defbe.name = strdup(args[1]);
2399 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002401 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002403
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002404 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2405 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 /* enable reconnections to dispatch */
2408 curproxy->options |= PR_O_REDISP;
2409 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002410 else if (!strcmp(args[0], "http-check")) {
2411 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002413
2414 if (strcmp(args[1], "disable-on-404") == 0) {
2415 /* enable a graceful server shutdown on an HTTP 404 response */
2416 curproxy->options |= PR_O_DISABLE404;
2417 }
2418 else {
2419 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002422 }
2423 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002424 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002425 if (curproxy == &defproxy) {
2426 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002429 }
2430
Willy Tarreaub80c2302007-11-30 20:51:32 +01002431 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002433
2434 if (strcmp(args[1], "fail") == 0) {
2435 /* add a condition to fail monitor requests */
2436 int pol = ACL_COND_NONE;
2437 struct acl_cond *cond;
2438
2439 if (!strcmp(args[2], "if"))
2440 pol = ACL_COND_IF;
2441 else if (!strcmp(args[2], "unless"))
2442 pol = ACL_COND_UNLESS;
2443
2444 if (pol == ACL_COND_NONE) {
2445 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2446 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002449 }
2450
2451 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2452 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2453 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002456 }
Willy Tarreau88922352009-10-04 22:02:50 +02002457 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002458 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002459 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002460 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2461 }
2462 else {
2463 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002466 }
2467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468#ifdef TPROXY
2469 else if (!strcmp(args[0], "transparent")) {
2470 /* enable transparent proxy connections */
2471 curproxy->options |= PR_O_TRANSP;
2472 }
2473#endif
2474 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002477
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 if (*(args[1]) == 0) {
2479 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 }
2483 curproxy->maxconn = atol(args[1]);
2484 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002485 else if (!strcmp(args[0], "backlog")) { /* backlog */
2486 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002488
2489 if (*(args[1]) == 0) {
2490 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002493 }
2494 curproxy->backlog = atol(args[1]);
2495 }
Willy Tarreau86034312006-12-29 00:10:33 +01002496 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002497 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002499
Willy Tarreau86034312006-12-29 00:10:33 +01002500 if (*(args[1]) == 0) {
2501 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002504 }
2505 curproxy->fullconn = atol(args[1]);
2506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2508 if (*(args[1]) == 0) {
2509 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002513 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2514 if (err) {
2515 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2516 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002519 }
2520 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 }
2522 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2523 if (curproxy == &defproxy) {
2524 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002528 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 if (strchr(args[1], ':') == NULL) {
2532 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 }
2536 curproxy->dispatch_addr = *str2sa(args[1]);
2537 }
2538 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002539 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002541
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002542 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002543 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2544 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002549 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2551 err_code |= ERR_WARN;
2552
2553 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2554 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2555 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2556 }
2557 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2558 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2559 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2560 }
2561 else {
2562 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
2565 }
2566 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002567 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002569 char *rport, *raddr;
2570 short realport = 0;
2571 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002573 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002578 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580
2581 if (!*args[2]) {
2582 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002587
2588 err = invalid_char(args[1]);
2589 if (err) {
2590 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2591 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002594 }
2595
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2597 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_ABORT;
2599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 }
2601
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002602 if (!defsrv) {
2603 /* the servers are linked backwards first */
2604 newsrv->next = curproxy->srv;
2605 curproxy->srv = newsrv;
2606 newsrv->proxy = curproxy;
2607 newsrv->conf.file = file;
2608 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002610 LIST_INIT(&newsrv->pendconns);
2611 do_check = 0;
2612 newsrv->state = SRV_RUNNING; /* early server setup */
2613 newsrv->last_change = now.tv_sec;
2614 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002616 /* several ways to check the port component :
2617 * - IP => port=+0, relative
2618 * - IP: => port=+0, relative
2619 * - IP:N => port=N, absolute
2620 * - IP:+N => port=+N, relative
2621 * - IP:-N => port=-N, relative
2622 */
2623 raddr = strdup(args[2]);
2624 rport = strchr(raddr, ':');
2625 if (rport) {
2626 *rport++ = 0;
2627 realport = atol(rport);
2628 if (!isdigit((unsigned char)*rport))
2629 newsrv->state |= SRV_MAPPORTS;
2630 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002632
2633 newsrv->addr = *str2sa(raddr);
2634 newsrv->addr.sin_port = htons(realport);
2635 free(raddr);
2636
2637 newsrv->check_port = curproxy->defsrv.check_port;
2638 newsrv->inter = curproxy->defsrv.inter;
2639 newsrv->fastinter = curproxy->defsrv.fastinter;
2640 newsrv->downinter = curproxy->defsrv.downinter;
2641 newsrv->rise = curproxy->defsrv.rise;
2642 newsrv->fall = curproxy->defsrv.fall;
2643 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2644 newsrv->minconn = curproxy->defsrv.minconn;
2645 newsrv->maxconn = curproxy->defsrv.maxconn;
2646 newsrv->slowstart = curproxy->defsrv.slowstart;
2647 newsrv->onerror = curproxy->defsrv.onerror;
2648 newsrv->consecutive_errors_limit
2649 = curproxy->defsrv.consecutive_errors_limit;
2650 newsrv->uweight = newsrv->iweight
2651 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002653 newsrv->curfd = -1; /* no health-check in progress */
2654 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002656 cur_arg = 3;
2657 } else {
2658 newsrv = &curproxy->defsrv;
2659 cur_arg = 1;
2660 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002661
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002663 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002664 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002665
2666 if (!*args[cur_arg + 1]) {
2667 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2668 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002671 }
2672
2673 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002674 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002675
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002676 if (newsrv->puid <= 0) {
2677 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002678 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002681 }
2682
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002683 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2684 if (node) {
2685 struct server *target = container_of(node, struct server, conf.id);
2686 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2687 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
2690 }
2691 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002692 cur_arg += 2;
2693 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002694 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 newsrv->cookie = strdup(args[cur_arg + 1]);
2696 newsrv->cklen = strlen(args[cur_arg + 1]);
2697 cur_arg += 2;
2698 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002699 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01002700 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2701 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2702 cur_arg += 2;
2703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002705 if (!*args[cur_arg + 1]) {
2706 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2707 file, linenum, args[cur_arg]);
2708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
2710 }
2711
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002713 if (newsrv->rise <= 0) {
2714 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2715 file, linenum, args[cur_arg]);
2716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
2718 }
2719
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 newsrv->health = newsrv->rise;
2721 cur_arg += 2;
2722 }
2723 else if (!strcmp(args[cur_arg], "fall")) {
2724 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002725
2726 if (!*args[cur_arg + 1]) {
2727 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2728 file, linenum, args[cur_arg]);
2729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
2731 }
2732
2733 if (newsrv->fall <= 0) {
2734 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2735 file, linenum, args[cur_arg]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
2738 }
2739
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 cur_arg += 2;
2741 }
2742 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002743 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2744 if (err) {
2745 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2746 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002749 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002750 if (val <= 0) {
2751 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2752 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002755 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002756 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 cur_arg += 2;
2758 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002759 else if (!strcmp(args[cur_arg], "fastinter")) {
2760 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2761 if (err) {
2762 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2763 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002766 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002767 if (val <= 0) {
2768 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2769 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002772 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002773 newsrv->fastinter = val;
2774 cur_arg += 2;
2775 }
2776 else if (!strcmp(args[cur_arg], "downinter")) {
2777 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2778 if (err) {
2779 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2780 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002783 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002784 if (val <= 0) {
2785 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2786 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_ALERT | ERR_FATAL;
2788 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002789 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002790 newsrv->downinter = val;
2791 cur_arg += 2;
2792 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002793 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002794 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002795 cur_arg += 2;
2796 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 else if (!strcmp(args[cur_arg], "port")) {
2798 newsrv->check_port = atol(args[cur_arg + 1]);
2799 cur_arg += 2;
2800 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002801 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 newsrv->state |= SRV_BACKUP;
2803 cur_arg ++;
2804 }
2805 else if (!strcmp(args[cur_arg], "weight")) {
2806 int w;
2807 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002808 if (w < 0 || w > 256) {
2809 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002814 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 cur_arg += 2;
2816 }
2817 else if (!strcmp(args[cur_arg], "minconn")) {
2818 newsrv->minconn = atol(args[cur_arg + 1]);
2819 cur_arg += 2;
2820 }
2821 else if (!strcmp(args[cur_arg], "maxconn")) {
2822 newsrv->maxconn = atol(args[cur_arg + 1]);
2823 cur_arg += 2;
2824 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002825 else if (!strcmp(args[cur_arg], "maxqueue")) {
2826 newsrv->maxqueue = atol(args[cur_arg + 1]);
2827 cur_arg += 2;
2828 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002829 else if (!strcmp(args[cur_arg], "slowstart")) {
2830 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002831 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002832 if (err) {
2833 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2834 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002837 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002838 if (val <= 0) {
2839 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2840 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002843 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002844 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002845 cur_arg += 2;
2846 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002847 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002848
2849 if (!*args[cur_arg + 1]) {
2850 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2851 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002854 }
2855
2856 newsrv->trackit = strdup(args[cur_arg + 1]);
2857
2858 cur_arg += 2;
2859 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002860 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 global.maxsock++;
2862 do_check = 1;
2863 cur_arg += 1;
2864 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002865 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002866 if (!strcmp(args[cur_arg + 1], "none"))
2867 newsrv->observe = HANA_OBS_NONE;
2868 else if (!strcmp(args[cur_arg + 1], "layer4"))
2869 newsrv->observe = HANA_OBS_LAYER4;
2870 else if (!strcmp(args[cur_arg + 1], "layer7")) {
2871 if (curproxy->mode != PR_MODE_HTTP) {
2872 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
2873 file, linenum, args[cur_arg + 1]);
2874 err_code |= ERR_ALERT;
2875 }
2876 newsrv->observe = HANA_OBS_LAYER7;
2877 }
2878 else {
2879 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
2880 "'l4events', 'http-responses' but get '%s'\n",
2881 file, linenum, args[cur_arg], args[cur_arg + 1]);
2882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
2884 }
2885
2886 cur_arg += 2;
2887 }
2888 else if (!strcmp(args[cur_arg], "on-error")) {
2889 if (!strcmp(args[cur_arg + 1], "fastinter"))
2890 newsrv->onerror = HANA_ONERR_FASTINTER;
2891 else if (!strcmp(args[cur_arg + 1], "fail-check"))
2892 newsrv->onerror = HANA_ONERR_FAILCHK;
2893 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
2894 newsrv->onerror = HANA_ONERR_SUDDTH;
2895 else if (!strcmp(args[cur_arg + 1], "mark-down"))
2896 newsrv->onerror = HANA_ONERR_MARKDWN;
2897 else {
2898 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
2899 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
2900 file, linenum, args[cur_arg], args[cur_arg + 1]);
2901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
2903 }
2904
2905 cur_arg += 2;
2906 }
2907 else if (!strcmp(args[cur_arg], "error-limit")) {
2908 if (!*args[cur_arg + 1]) {
2909 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2910 file, linenum, args[cur_arg]);
2911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
2914
2915 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
2916
2917 if (newsrv->consecutive_errors_limit <= 0) {
2918 Alert("parsing [%s:%d]: %s has to be > 0.\n",
2919 file, linenum, args[cur_arg]);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002924 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002925 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002927#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002928 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002929 file, linenum, "source", "usesrc");
2930#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002931 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002933#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 }
2937 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002938 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2939
2940 if (port_low != port_high) {
2941 int i;
2942 if (port_low <= 0 || port_low > 65535 ||
2943 port_high <= 0 || port_high > 65535 ||
2944 port_low > port_high) {
2945 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2946 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002949 }
2950 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2951 for (i = 0; i < newsrv->sport_range->size; i++)
2952 newsrv->sport_range->ports[i] = port_low + i;
2953 }
2954
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002956 while (*(args[cur_arg])) {
2957 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002958#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2959#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002960 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2961 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2962 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002965 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002966#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002967 if (!*args[cur_arg + 1]) {
2968 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2969 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002972 }
2973 if (!strcmp(args[cur_arg + 1], "client")) {
2974 newsrv->state |= SRV_TPROXY_CLI;
2975 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2976 newsrv->state |= SRV_TPROXY_CIP;
2977 } else {
2978 newsrv->state |= SRV_TPROXY_ADDR;
2979 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2980 }
2981 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002982#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002983 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002984#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002985 cur_arg += 2;
2986 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002987#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002988 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002989 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002992#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2993 } /* "usesrc" */
2994
2995 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2996#ifdef SO_BINDTODEVICE
2997 if (!*args[cur_arg + 1]) {
2998 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2999 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003002 }
3003 if (newsrv->iface_name)
3004 free(newsrv->iface_name);
3005
3006 newsrv->iface_name = strdup(args[cur_arg + 1]);
3007 newsrv->iface_len = strlen(newsrv->iface_name);
3008 global.last_checks |= LSTCHK_NETADM;
3009#else
3010 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3011 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003014#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003015 cur_arg += 2;
3016 continue;
3017 }
3018 /* this keyword in not an option of "source" */
3019 break;
3020 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003022 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003023 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3024 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003029 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003030 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003031 file, linenum, newsrv->id);
3032 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003033 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003034 file, linenum);
3035
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 }
3039 }
3040
3041 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003042 if (newsrv->trackit) {
3043 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3044 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003047 }
3048
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003049 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3050 newsrv->check_port = newsrv->check_addr.sin_port;
3051
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3053 newsrv->check_port = realport; /* by default */
3054 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003055 /* not yet valid, because no port was set on
3056 * the server either. We'll check if we have
3057 * a known port on the first listener.
3058 */
3059 struct listener *l;
3060 l = curproxy->listen;
3061 if (l) {
3062 int port;
3063 port = (l->addr.ss_family == AF_INET6)
3064 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3065 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3066 newsrv->check_port = port;
3067 }
3068 }
3069 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3071 file, linenum, newsrv->id);
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 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003075
3076 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 newsrv->state |= SRV_CHECKED;
3078 }
3079
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003080 if (!defsrv) {
3081 if (newsrv->state & SRV_BACKUP)
3082 curproxy->srv_bck++;
3083 else
3084 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003085
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003086 newsrv->prev_state = newsrv->state;
3087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 }
3089 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003090 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 int facility;
3092
3093 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3094 curproxy->logfac1 = global.logfac1;
3095 curproxy->logsrv1 = global.logsrv1;
3096 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003097 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 curproxy->logfac2 = global.logfac2;
3099 curproxy->logsrv2 = global.logsrv2;
3100 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003101 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 }
3103 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003104 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105
3106 facility = get_log_facility(args[2]);
3107 if (facility < 0) {
3108 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3109 exit(1);
3110 }
3111
3112 level = 7; /* max syslog level = debug */
3113 if (*(args[3])) {
3114 level = get_log_level(args[3]);
3115 if (level < 0) {
3116 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3117 exit(1);
3118 }
3119 }
3120
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003121 minlvl = 0; /* limit syslog level to this level (emerg) */
3122 if (*(args[4])) {
3123 minlvl = get_log_level(args[4]);
3124 if (level < 0) {
3125 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3126 exit(1);
3127 }
3128 }
3129
Robert Tsai81ae1952007-12-05 10:47:29 +01003130 if (args[1][0] == '/') {
3131 logsrv.u.addr.sa_family = AF_UNIX;
3132 logsrv.u.un = *str2sun(args[1]);
3133 } else {
3134 logsrv.u.addr.sa_family = AF_INET;
3135 logsrv.u.in = *str2sa(args[1]);
3136 if (!logsrv.u.in.sin_port) {
3137 logsrv.u.in.sin_port =
3138 htons(SYSLOG_PORT);
3139 }
3140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141
3142 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003143 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 curproxy->logfac1 = facility;
3145 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003146 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003149 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 curproxy->logfac2 = facility;
3151 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003152 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
3154 else {
3155 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159 }
3160 else {
3161 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3162 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
3166 }
3167 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003168 int cur_arg;
3169
Willy Tarreau977b8e42006-12-29 14:19:17 +01003170 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003172
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003174 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3175 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003179
3180 /* we must first clear any optional default setting */
3181 curproxy->options &= ~PR_O_TPXY_MASK;
3182 free(curproxy->iface_name);
3183 curproxy->iface_name = NULL;
3184 curproxy->iface_len = 0;
3185
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 curproxy->source_addr = *str2sa(args[1]);
3187 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003188
3189 cur_arg = 2;
3190 while (*(args[cur_arg])) {
3191 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003192#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3193#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003194 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3195 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3196 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003199 }
3200#endif
3201 if (!*args[cur_arg + 1]) {
3202 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3203 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003206 }
3207
3208 if (!strcmp(args[cur_arg + 1], "client")) {
3209 curproxy->options |= PR_O_TPXY_CLI;
3210 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3211 curproxy->options |= PR_O_TPXY_CIP;
3212 } else {
3213 curproxy->options |= PR_O_TPXY_ADDR;
3214 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3215 }
3216 global.last_checks |= LSTCHK_NETADM;
3217#if !defined(CONFIG_HAP_LINUX_TPROXY)
3218 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003219#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003220#else /* no TPROXY support */
3221 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003222 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003225#endif
3226 cur_arg += 2;
3227 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003228 }
3229
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003230 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3231#ifdef SO_BINDTODEVICE
3232 if (!*args[cur_arg + 1]) {
3233 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003237 }
3238 if (curproxy->iface_name)
3239 free(curproxy->iface_name);
3240
3241 curproxy->iface_name = strdup(args[cur_arg + 1]);
3242 curproxy->iface_len = strlen(curproxy->iface_name);
3243 global.last_checks |= LSTCHK_NETADM;
3244#else
3245 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3246 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003249#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003250 cur_arg += 2;
3251 continue;
3252 }
3253 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3254 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003259 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3260 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3261 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3266 regex_t *preg;
3267 if (curproxy == &defproxy) {
3268 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003272 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003274
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 if (*(args[1]) == 0 || *(args[2]) == 0) {
3276 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3277 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 }
3281
3282 preg = calloc(1, sizeof(regex_t));
3283 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3284 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 }
3288
3289 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3290 if (err) {
3291 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3292 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003295 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
3297 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3298 regex_t *preg;
3299 if (curproxy == &defproxy) {
3300 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003304 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003306
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 if (*(args[1]) == 0) {
3308 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
3312
3313 preg = calloc(1, sizeof(regex_t));
3314 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3315 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
3319
3320 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003321 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
3323 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3324 regex_t *preg;
3325 if (curproxy == &defproxy) {
3326 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003330 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003332
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 if (*(args[1]) == 0) {
3334 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
3338
3339 preg = calloc(1, sizeof(regex_t));
3340 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3341 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
3345
3346 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003347 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
3349 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3350 regex_t *preg;
3351 if (curproxy == &defproxy) {
3352 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003356 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003358
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 if (*(args[1]) == 0) {
3360 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
3364
3365 preg = calloc(1, sizeof(regex_t));
3366 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3367 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 }
3371
3372 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003373 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
3375 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3376 regex_t *preg;
3377 if (curproxy == &defproxy) {
3378 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003382 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003384
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 if (*(args[1]) == 0) {
3386 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
3390
3391 preg = calloc(1, sizeof(regex_t));
3392 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3393 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 }
3397
3398 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003399 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003401 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3402 regex_t *preg;
3403 if (curproxy == &defproxy) {
3404 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003407 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003408 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003410
Willy Tarreaub8750a82006-09-03 09:56:00 +02003411 if (*(args[1]) == 0) {
3412 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003415 }
3416
3417 preg = calloc(1, sizeof(regex_t));
3418 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3419 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003422 }
3423
3424 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003425 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003426 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003427 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3428 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003429 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003433 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003434 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003435 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003436
Willy Tarreau977b8e42006-12-29 14:19:17 +01003437 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003438 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003442 }
3443
3444 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003445 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003446 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003449 }
3450
3451 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003452 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003453 }
3454 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3455 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003456 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003457 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003460 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003461 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003462 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003463
Willy Tarreau977b8e42006-12-29 14:19:17 +01003464 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003465 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3466 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003469 }
3470
3471 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003472 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003473 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003476 }
3477
3478 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003479 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3482 regex_t *preg;
3483 if (curproxy == &defproxy) {
3484 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003488 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003490
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 if (*(args[1]) == 0 || *(args[2]) == 0) {
3492 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3493 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 }
3497
3498 preg = calloc(1, sizeof(regex_t));
3499 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3500 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
3504
3505 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3506 if (err) {
3507 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3508 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003512 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 }
3514 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
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 <regex> 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 | REG_ICASE) != 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 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003538 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }
3540 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3541 regex_t *preg;
3542 if (curproxy == &defproxy) {
3543 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003547 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003549
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 if (*(args[1]) == 0) {
3551 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
3555
3556 preg = calloc(1, sizeof(regex_t));
3557 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3558 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 }
3562
3563 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003564 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
3566 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3567 regex_t *preg;
3568 if (curproxy == &defproxy) {
3569 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003573 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003575
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 if (*(args[1]) == 0) {
3577 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
3581
3582 preg = calloc(1, sizeof(regex_t));
3583 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3584 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
3588
3589 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003590 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
3592 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3593 regex_t *preg;
3594 if (curproxy == &defproxy) {
3595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003599 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003601
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 if (*(args[1]) == 0) {
3603 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
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 preg = calloc(1, sizeof(regex_t));
3609 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3610 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 }
3614
3615 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003616 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003618 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3619 regex_t *preg;
3620 if (curproxy == &defproxy) {
3621 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003624 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003625 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003626 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003627
Willy Tarreaub8750a82006-09-03 09:56:00 +02003628 if (*(args[1]) == 0) {
3629 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003632 }
3633
3634 preg = calloc(1, sizeof(regex_t));
3635 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3636 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003639 }
3640
3641 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003642 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003645 struct wordlist *wl;
3646
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 if (curproxy == &defproxy) {
3648 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003652 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 if (*(args[1]) == 0) {
3656 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003660
3661 wl = calloc(1, sizeof(*wl));
3662 wl->s = strdup(args[1]);
3663 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003664 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 }
3666 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3667 regex_t *preg;
3668
3669 if (*(args[1]) == 0 || *(args[2]) == 0) {
3670 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3671 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003674 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003675 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003677
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 preg = calloc(1, sizeof(regex_t));
3679 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3680 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 }
3684
3685 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3686 if (err) {
3687 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3688 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003692 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 }
3694 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3695 regex_t *preg;
3696 if (curproxy == &defproxy) {
3697 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003701 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003703
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 if (*(args[1]) == 0) {
3705 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
3709
3710 preg = calloc(1, sizeof(regex_t));
3711 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3712 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
3716
3717 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3718 if (err) {
3719 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3720 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
3724 }
3725 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3726 regex_t *preg;
3727 if (curproxy == &defproxy) {
3728 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003732 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003734
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 if (*(args[1]) == 0) {
3736 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 }
3740
3741 preg = calloc(1, sizeof(regex_t));
3742 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3743 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 }
3747
3748 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3749 if (err) {
3750 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3751 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 }
3755 }
3756 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3757 regex_t *preg;
3758 if (curproxy == &defproxy) {
3759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003763 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765
3766 if (*(args[1]) == 0 || *(args[2]) == 0) {
3767 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3768 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 }
3772
3773 preg = calloc(1, sizeof(regex_t));
3774 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3775 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
3779
3780 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3781 if (err) {
3782 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3783 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 }
3787 }
3788 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3789 regex_t *preg;
3790 if (curproxy == &defproxy) {
3791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003795 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003797
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 if (*(args[1]) == 0) {
3799 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 }
3803
3804 preg = calloc(1, sizeof(regex_t));
3805 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3806 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810
3811 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3812 if (err) {
3813 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3814 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818 }
3819 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3820 regex_t *preg;
3821 if (curproxy == &defproxy) {
3822 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003826 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003828
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 if (*(args[1]) == 0) {
3830 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
3834
3835 preg = calloc(1, sizeof(regex_t));
3836 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3837 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 }
3841
3842 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3843 if (err) {
3844 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3845 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
3849 }
3850 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003851 struct wordlist *wl;
3852
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 if (curproxy == &defproxy) {
3854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003858 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 if (*(args[1]) == 0) {
3862 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 }
3866
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003867 wl = calloc(1, sizeof(*wl));
3868 wl->s = strdup(args[1]);
3869 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003870 }
3871 else if (!strcmp(args[0], "errorloc") ||
3872 !strcmp(args[0], "errorloc302") ||
3873 !strcmp(args[0], "errorloc303")) { /* error location */
3874 int errnum, errlen;
3875 char *err;
3876
Willy Tarreau977b8e42006-12-29 14:19:17 +01003877 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003879
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003881 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 }
3885
3886 errnum = atol(args[1]);
3887 if (!strcmp(args[0], "errorloc303")) {
3888 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3889 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3890 } else {
3891 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3892 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3893 }
3894
Willy Tarreau0f772532006-12-23 20:51:41 +01003895 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3896 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003897 chunk_destroy(&curproxy->errmsg[rc]);
3898 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003899 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003902
3903 if (rc >= HTTP_ERR_SIZE) {
3904 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3905 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 free(err);
3907 }
3908 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003909 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3910 int errnum, errlen, fd;
3911 char *err;
3912 struct stat stat;
3913
3914 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003916
3917 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003918 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003921 }
3922
3923 fd = open(args[2], O_RDONLY);
3924 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3925 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3926 file, linenum, args[2], args[1]);
3927 if (fd >= 0)
3928 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003931 }
3932
Willy Tarreau27a674e2009-08-17 07:23:33 +02003933 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003934 errlen = stat.st_size;
3935 } else {
3936 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003937 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003939 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003940 }
3941
3942 err = malloc(errlen); /* malloc() must succeed during parsing */
3943 errnum = read(fd, err, errlen);
3944 if (errnum != errlen) {
3945 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3946 file, linenum, args[2], args[1]);
3947 close(fd);
3948 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003951 }
3952 close(fd);
3953
3954 errnum = atol(args[1]);
3955 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3956 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003957 chunk_destroy(&curproxy->errmsg[rc]);
3958 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003959 break;
3960 }
3961 }
3962
3963 if (rc >= HTTP_ERR_SIZE) {
3964 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3965 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003967 free(err);
3968 }
3969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003971 struct cfg_kw_list *kwl;
3972 int index;
3973
3974 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3975 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3976 if (kwl->kw[index].section != CFG_LISTEN)
3977 continue;
3978 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3979 /* prepare error message just in case */
3980 snprintf(trash, sizeof(trash),
3981 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003982 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3983 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003984 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003987 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003988 else if (rc > 0) {
3989 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_WARN;
3991 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003992 }
Willy Tarreau93893792009-07-23 13:19:11 +02003993 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003994 }
3995 }
3996 }
3997
Willy Tarreau6daf3432008-01-22 16:44:08 +01003998 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 }
Willy Tarreau93893792009-07-23 13:19:11 +02004002 out:
4003 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004}
4005
4006
4007/*
4008 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004009 * Returns the error code, 0 if OK, or any combination of :
4010 * - ERR_ABORT: must abort ASAP
4011 * - ERR_FATAL: we can continue parsing but not start the service
4012 * - ERR_WARN: a warning has been emitted
4013 * - ERR_ALERT: an alert has been emitted
4014 * Only the two first ones can stop processing, the two others are just
4015 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004017int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004019 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020 FILE *f;
4021 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004023 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 if ((f=fopen(file,"r")) == NULL)
4026 return -1;
4027
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004028 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004029 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004030 char *end;
4031 char *args[MAX_LINE_ARGS + 1];
4032 char *line = thisline;
4033
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 linenum++;
4035
4036 end = line + strlen(line);
4037
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004038 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4039 /* Check if we reached the limit and the last char is not \n.
4040 * Watch out for the last line without the terminating '\n'!
4041 */
4042 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004043 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004044 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004045 }
4046
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004048 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 line++;
4050
4051 arg = 0;
4052 args[arg] = line;
4053
4054 while (*line && arg < MAX_LINE_ARGS) {
4055 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4056 * C equivalent value. Other combinations left unchanged (eg: \1).
4057 */
4058 if (*line == '\\') {
4059 int skip = 0;
4060 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4061 *line = line[1];
4062 skip = 1;
4063 }
4064 else if (line[1] == 'r') {
4065 *line = '\r';
4066 skip = 1;
4067 }
4068 else if (line[1] == 'n') {
4069 *line = '\n';
4070 skip = 1;
4071 }
4072 else if (line[1] == 't') {
4073 *line = '\t';
4074 skip = 1;
4075 }
4076 else if (line[1] == 'x') {
4077 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
4078 unsigned char hex1, hex2;
4079 hex1 = toupper(line[2]) - '0';
4080 hex2 = toupper(line[3]) - '0';
4081 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4082 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4083 *line = (hex1<<4) + hex2;
4084 skip = 3;
4085 }
4086 else {
4087 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004088 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089 }
4090 }
4091 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004092 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093 end -= skip;
4094 }
4095 line++;
4096 }
4097 else if (*line == '#' || *line == '\n' || *line == '\r') {
4098 /* end of string, end of loop */
4099 *line = 0;
4100 break;
4101 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004102 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004104 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004105 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106 line++;
4107 args[++arg] = line;
4108 }
4109 else {
4110 line++;
4111 }
4112 }
4113
4114 /* empty line */
4115 if (!**args)
4116 continue;
4117
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004118 if (*line) {
4119 /* we had to stop due to too many args.
4120 * Let's terminate the string, print the offending part then cut the
4121 * last arg.
4122 */
4123 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4124 line++;
4125 *line = '\0';
4126
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004127 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004128 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004129 err_code |= ERR_ALERT | ERR_FATAL;
4130 args[arg] = line;
4131 }
4132
Willy Tarreau540abe42007-05-02 20:50:16 +02004133 /* zero out remaining args and ensure that at least one entry
4134 * is zeroed out.
4135 */
4136 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 args[arg] = line;
4138 }
4139
Willy Tarreau3842f002009-06-14 11:39:52 +02004140 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004141 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004142 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004143 for (arg=0; *args[arg+1]; arg++)
4144 args[arg] = args[arg+1]; // shift args after inversion
4145 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004146 else if (!strcmp(args[0], "default")) {
4147 kwm = KWM_DEF;
4148 for (arg=0; *args[arg+1]; arg++)
4149 args[arg] = args[arg+1]; // shift args after inversion
4150 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004151
Willy Tarreau3842f002009-06-14 11:39:52 +02004152 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4153 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004155 }
4156
Willy Tarreau977b8e42006-12-29 14:19:17 +01004157 if (!strcmp(args[0], "listen") ||
4158 !strcmp(args[0], "frontend") ||
4159 !strcmp(args[0], "backend") ||
4160 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004161 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004163 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004164 cursection = strdup(args[0]);
4165 }
4166 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004168 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004169 cursection = strdup(args[0]);
4170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 /* else it's a section keyword */
4172
4173 switch (confsect) {
4174 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 break;
4177 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004178 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 break;
4180 default:
4181 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004184
4185 if (err_code & ERR_ABORT)
4186 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004188 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004189 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004191 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004192}
4193
Willy Tarreaubb925012009-07-23 13:36:36 +02004194/*
4195 * Returns the error code, 0 if OK, or any combination of :
4196 * - ERR_ABORT: must abort ASAP
4197 * - ERR_FATAL: we can continue parsing but not start the service
4198 * - ERR_WARN: a warning has been emitted
4199 * - ERR_ALERT: an alert has been emitted
4200 * Only the two first ones can stop processing, the two others are just
4201 * indicators.
4202 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004203int check_config_validity()
4204{
4205 int cfgerr = 0;
4206 struct proxy *curproxy = NULL;
4207 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004208 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004209 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210
4211 /*
4212 * Now, check for the integrity of all that we have collected.
4213 */
4214
4215 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004216 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004217
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004218 /* first, we will invert the proxy list order */
4219 curproxy = NULL;
4220 while (proxy) {
4221 struct proxy *next;
4222
4223 next = proxy->next;
4224 proxy->next = curproxy;
4225 curproxy = proxy;
4226 if (!next)
4227 break;
4228 proxy = next;
4229 }
4230
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004232 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 }
4236
4237 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004238 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004239 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004240 unsigned int next_id;
4241
4242 if (!curproxy->uuid) {
4243 /* proxy ID not set, use automatic numbering with first
4244 * spare entry starting with next_pxid.
4245 */
4246 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4247 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4248 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4249 next_pxid++;
4250 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004251
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004253 /* ensure we don't keep listeners uselessly bound */
4254 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 curproxy = curproxy->next;
4256 continue;
4257 }
4258
Willy Tarreauff01a212009-03-15 13:46:16 +01004259 switch (curproxy->mode) {
4260 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004261 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004262 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004263 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4264 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004265 cfgerr++;
4266 }
4267
4268 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004269 Warning("config : servers will be ignored for %s '%s'.\n",
4270 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004271 break;
4272
4273 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004274 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004275 break;
4276
4277 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004278 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004279 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004280 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4281 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004282 cfgerr++;
4283 }
4284 break;
4285 }
4286
4287 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004288 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4289 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 cfgerr++;
4291 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004292
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004293 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004294 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004295 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004296 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4297 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004298 cfgerr++;
4299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004301 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004302 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4303 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004304 cfgerr++;
4305 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004307 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004308 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4309 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004310 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004311 }
4312 }
4313 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4314 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4315 /* If no LB algo is set in a backend, and we're not in
4316 * transparent mode, dispatch mode nor proxy mode, we
4317 * want to use balance roundrobin by default.
4318 */
4319 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4320 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004321 }
4322 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004323
Willy Tarreau82936582007-11-30 15:20:09 +01004324 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4325 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004326 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4327 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004328 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004329 }
4330
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004331 /* if a default backend was specified, let's find it */
4332 if (curproxy->defbe.name) {
4333 struct proxy *target;
4334
Alex Williams96532db2009-11-01 21:27:13 -05004335 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004336 if (!target) {
4337 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4338 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004339 cfgerr++;
4340 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004341 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4342 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004343 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004344 } else {
4345 free(curproxy->defbe.name);
4346 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004347 /* we force the backend to be present on at least all of
4348 * the frontend's processes.
4349 */
4350 target->bind_proc = curproxy->bind_proc ?
4351 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 }
4353 }
4354
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004355 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004356 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4357 /* map jump target for ACT_SETBE in req_rep chain */
4358 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004359 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004360 struct proxy *target;
4361
Willy Tarreaua496b602006-12-17 23:15:24 +01004362 if (exp->action != ACT_SETBE)
4363 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004364
Alex Williams96532db2009-11-01 21:27:13 -05004365 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004366 if (!target) {
4367 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4368 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004369 cfgerr++;
4370 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004371 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4372 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004373 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004374 } else {
4375 free((void *)exp->replace);
4376 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004377 /* we force the backend to be present on at least all of
4378 * the frontend's processes.
4379 */
4380 target->bind_proc = curproxy->bind_proc ?
4381 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004382 }
4383 }
4384 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004385
4386 /* find the target proxy for 'use_backend' rules */
4387 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004388 struct proxy *target;
4389
Alex Williams96532db2009-11-01 21:27:13 -05004390 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004391
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004392 if (!target) {
4393 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4394 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004395 cfgerr++;
4396 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004397 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4398 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004399 cfgerr++;
4400 } else {
4401 free((void *)rule->be.name);
4402 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004403 /* we force the backend to be present on at least all of
4404 * the frontend's processes.
4405 */
4406 target->bind_proc = curproxy->bind_proc ?
4407 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004408 }
4409 }
4410
Willy Tarreau2738a142006-07-08 17:28:09 +02004411 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004412 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004413 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004414 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004415 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004416 " | While not properly invalid, you will certainly encounter various problems\n"
4417 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004418 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004419 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004420 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004421 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004422
Willy Tarreau1fa31262007-12-03 00:36:16 +01004423 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4424 * We must still support older configurations, so let's find out whether those
4425 * parameters have been set or must be copied from contimeouts.
4426 */
4427 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004428 if (!curproxy->timeout.tarpit ||
4429 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004430 /* tarpit timeout not set. We search in the following order:
4431 * default.tarpit, curr.connect, default.connect.
4432 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004433 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004434 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004435 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004436 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004437 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004438 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004439 }
4440 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004441 (!curproxy->timeout.queue ||
4442 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004443 /* queue timeout not set. We search in the following order:
4444 * default.queue, curr.connect, default.connect.
4445 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004446 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004447 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004448 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004449 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004450 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004451 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004452 }
4453 }
4454
Willy Tarreauf3c69202006-07-09 16:42:34 +02004455 if (curproxy->options & PR_O_SSL3_CHK) {
4456 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4457 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4458 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4459 }
4460
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004461 /* The small pools required for the capture lists */
4462 if (curproxy->nb_req_cap)
4463 curproxy->req_cap_pool = create_pool("ptrcap",
4464 curproxy->nb_req_cap * sizeof(char *),
4465 MEM_F_SHARED);
4466 if (curproxy->nb_rsp_cap)
4467 curproxy->rsp_cap_pool = create_pool("ptrcap",
4468 curproxy->nb_rsp_cap * sizeof(char *),
4469 MEM_F_SHARED);
4470
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004471 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4472 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4473 MEM_F_SHARED);
4474
Willy Tarreau86034312006-12-29 00:10:33 +01004475 /* for backwards compatibility with "listen" instances, if
4476 * fullconn is not set but maxconn is set, then maxconn
4477 * is used.
4478 */
4479 if (!curproxy->fullconn)
4480 curproxy->fullconn = curproxy->maxconn;
4481
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 /* first, we will invert the servers list order */
4483 newsrv = NULL;
4484 while (curproxy->srv) {
4485 struct server *next;
4486
4487 next = curproxy->srv->next;
4488 curproxy->srv->next = newsrv;
4489 newsrv = curproxy->srv;
4490 if (!next)
4491 break;
4492 curproxy->srv = next;
4493 }
4494
Willy Tarreau20697042007-11-15 23:26:18 +01004495 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004496 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004498 /* We have to initialize the server lookup mechanism depending
4499 * on what LB algorithm was choosen.
4500 */
4501
4502 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4503 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4504 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004505 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4506 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4507 init_server_map(curproxy);
4508 } else {
4509 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4510 fwrr_init_server_groups(curproxy);
4511 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004512 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004513
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004514 case BE_LB_KIND_LC:
4515 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004516 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004517 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004518
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004519 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004520 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4521 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4522 chash_init_server_tree(curproxy);
4523 } else {
4524 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4525 init_server_map(curproxy);
4526 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004527 break;
4528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529
4530 if (curproxy->options & PR_O_LOGASAP)
4531 curproxy->to_log &= ~LW_BYTES;
4532
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004533 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4534 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4535 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4536 proxy_type_str(curproxy), curproxy->id);
4537 err_code |= ERR_WARN;
4538 }
4539
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004541 * ensure that we're not cross-dressing a TCP server into HTTP.
4542 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004543 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004544 newsrv = curproxy->srv;
4545 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004546 if (!newsrv->puid) {
4547 /* server ID not set, use automatic numbering with first
4548 * spare entry starting with next_svid.
4549 */
4550 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4551 newsrv->conf.id.key = newsrv->puid = next_id;
4552 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4553 next_id++;
4554 }
4555
Willy Tarreau21d2af32008-02-14 20:25:24 +01004556 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004557 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4558 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004559 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004560 }
4561 newsrv = newsrv->next;
4562 }
4563
4564 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565 * If this server supports a maxconn parameter, it needs a dedicated
4566 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004567 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 */
4569 newsrv = curproxy->srv;
4570 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004571 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 /* Only 'minconn' was specified, or it was higher than or equal
4573 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4574 * this will avoid further useless expensive computations.
4575 */
4576 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004577 } else if (newsrv->maxconn && !newsrv->minconn) {
4578 /* minconn was not specified, so we set it to maxconn */
4579 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004580 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004581 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4582 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004583 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 }
4585
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004586 if (newsrv->trackit) {
4587 struct proxy *px;
4588 struct server *srv;
4589 char *pname, *sname;
4590
4591 pname = newsrv->trackit;
4592 sname = strrchr(pname, '/');
4593
4594 if (sname)
4595 *sname++ = '\0';
4596 else {
4597 sname = pname;
4598 pname = NULL;
4599 }
4600
4601 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004602 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004603 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004604 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4605 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004606 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004607 cfgerr++;
4608 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004609 }
4610 } else
4611 px = curproxy;
4612
4613 srv = findserver(px, sname);
4614 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004615 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4616 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004617 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004618 cfgerr++;
4619 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004620 }
4621
4622 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004623 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004624 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004625 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004626 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004627 cfgerr++;
4628 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004629 }
4630
4631 if (curproxy != px &&
4632 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004633 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004634 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004635 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004636 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004637 cfgerr++;
4638 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004639 }
4640
4641 newsrv->tracked = srv;
4642 newsrv->tracknext = srv->tracknext;
4643 srv->tracknext = newsrv;
4644
4645 free(newsrv->trackit);
4646 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004647 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 newsrv = newsrv->next;
4649 }
4650
Willy Tarreauc1a21672009-08-16 22:37:44 +02004651 if (curproxy->cap & PR_CAP_FE) {
4652 if (curproxy->tcp_req.inspect_delay ||
4653 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4654 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4655
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004656 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004657 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004658 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004659 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004660
4661 /* both TCP and HTTP must check switching rules */
4662 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4663 }
4664
4665 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004666 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004667 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004668 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004669 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004670
4671 /* If the backend does requires RDP cookie persistence, we have to
4672 * enable the corresponding analyser.
4673 */
4674 if (curproxy->options2 & PR_O2_RDPC_PRST)
4675 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4676 }
4677
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004678 listener = NULL;
4679 while (curproxy->listen) {
4680 struct listener *next;
4681
4682 next = curproxy->listen->next;
4683 curproxy->listen->next = listener;
4684 listener = curproxy->listen;
4685
4686 if (!next)
4687 break;
4688
4689 curproxy->listen = next;
4690 }
4691
Willy Tarreaue6b98942007-10-29 01:09:36 +01004692 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004693 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004694 listener = curproxy->listen;
4695 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004696 if (!listener->luid) {
4697 /* listener ID not set, use automatic numbering with first
4698 * spare entry starting with next_luid.
4699 */
4700 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4701 listener->conf.id.key = listener->luid = next_id;
4702 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4703 next_id++;
4704 }
4705
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004706 /* enable separate counters */
4707 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4708 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4709 if (!listener->name) {
4710 sprintf(trash, "sock-%d", listener->luid);
4711 listener->name = strdup(trash);
4712 }
4713 }
4714
Willy Tarreaue6b98942007-10-29 01:09:36 +01004715 if (curproxy->options & PR_O_TCP_NOLING)
4716 listener->options |= LI_O_NOLINGER;
4717 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004718 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004719 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004720 listener->accept = event_accept;
4721 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004722 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004723 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004724
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004725 /* smart accept mode is automatic in HTTP mode */
4726 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4727 (curproxy->mode == PR_MODE_HTTP &&
4728 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4729 listener->options |= LI_O_NOQUICKACK;
4730
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004731 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004732 listener = listener->next;
4733 }
4734
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 curproxy = curproxy->next;
4736 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004737
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004738 /*
4739 * Recount currently required checks.
4740 */
4741
4742 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4743 int optnum;
4744
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004745 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4746 if (curproxy->options & cfg_opts[optnum].val)
4747 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004748
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004749 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4750 if (curproxy->options2 & cfg_opts2[optnum].val)
4751 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004752 }
4753
Willy Tarreaubb925012009-07-23 13:36:36 +02004754 if (cfgerr > 0)
4755 err_code |= ERR_ALERT | ERR_FATAL;
4756 out:
4757 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758}
4759
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004760/*
4761 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4762 * parsing sessions.
4763 */
4764void cfg_register_keywords(struct cfg_kw_list *kwl)
4765{
4766 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4767}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004769/*
4770 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4771 */
4772void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4773{
4774 LIST_DEL(&kwl->list);
4775 LIST_INIT(&kwl->list);
4776}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777
4778/*
4779 * Local variables:
4780 * c-indent-level: 8
4781 * c-basic-offset: 8
4782 * End:
4783 */