blob: 7a7af790c733f2375d747895182bac648aeb7f1c [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;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002230 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002231 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 if (!*args[2]) { /* no argument */
2233 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2234 curproxy->check_len = strlen(DEF_CHECK_REQ);
2235 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002236 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 curproxy->check_req = (char *)malloc(reqlen);
2238 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2239 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2240 } else { /* more arguments : METHOD URI [HTTP_VER] */
2241 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2242 if (*args[4])
2243 reqlen += strlen(args[4]);
2244 else
2245 reqlen += strlen("HTTP/1.0");
2246
2247 curproxy->check_req = (char *)malloc(reqlen);
2248 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2249 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2250 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002251 }
2252 else if (!strcmp(args[1], "ssl-hello-chk")) {
2253 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002254 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002256
Willy Tarreaua534fea2008-08-03 12:19:50 +02002257 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002258 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002259 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002260 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002261 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
Willy Tarreau23677902007-05-08 23:50:35 +02002263 else if (!strcmp(args[1], "smtpchk")) {
2264 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002265 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002266 curproxy->options &= ~PR_O_HTTP_CHK;
2267 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002268 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002269 curproxy->options |= PR_O_SMTP_CHK;
2270
2271 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2272 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2273 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2274 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2275 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2276 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2277 curproxy->check_req = (char *)malloc(reqlen);
2278 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2279 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2280 } else {
2281 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2282 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2283 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2284 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2285 }
2286 }
2287 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002288 else if (!strcmp(args[1], "mysql-check")) {
2289 /* use MYSQL request to check servers' health */
2290 free(curproxy->check_req);
2291 curproxy->options &= ~PR_O_HTTP_CHK;
2292 curproxy->options &= ~PR_O_SSL3_CHK;
2293 curproxy->options &= ~PR_O_SMTP_CHK;
2294 curproxy->options2 |= PR_O2_MYSQL_CHK;
2295 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002296 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002297 int cur_arg;
2298
2299 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2300 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002301 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002302
2303 curproxy->options |= PR_O_FWDFOR;
2304
2305 free(curproxy->fwdfor_hdr_name);
2306 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2307 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2308
2309 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2310 cur_arg = 2;
2311 while (*(args[cur_arg])) {
2312 if (!strcmp(args[cur_arg], "except")) {
2313 /* suboption except - needs additional argument for it */
2314 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2315 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002319 }
2320 /* flush useless bits */
2321 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002322 cur_arg += 2;
2323 } else if (!strcmp(args[cur_arg], "header")) {
2324 /* suboption header - needs additional argument for it */
2325 if (*(args[cur_arg+1]) == 0) {
2326 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2327 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002330 }
2331 free(curproxy->fwdfor_hdr_name);
2332 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2333 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2334 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002335 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002336 /* unknown suboption - catchall */
2337 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2338 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002341 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002342 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002343 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002344 else if (!strcmp(args[1], "originalto")) {
2345 int cur_arg;
2346
2347 /* insert x-original-to field, but not for the IP address listed as an except.
2348 * set default options (ie: bitfield, header name, etc)
2349 */
2350
2351 curproxy->options |= PR_O_ORGTO;
2352
2353 free(curproxy->orgto_hdr_name);
2354 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2355 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2356
2357 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2358 cur_arg = 2;
2359 while (*(args[cur_arg])) {
2360 if (!strcmp(args[cur_arg], "except")) {
2361 /* suboption except - needs additional argument for it */
2362 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2363 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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 /* flush useless bits */
2369 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2370 cur_arg += 2;
2371 } else if (!strcmp(args[cur_arg], "header")) {
2372 /* suboption header - needs additional argument for it */
2373 if (*(args[cur_arg+1]) == 0) {
2374 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2375 file, linenum, args[0], args[1], args[cur_arg]);
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 free(curproxy->orgto_hdr_name);
2380 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2381 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2382 cur_arg += 2;
2383 } else {
2384 /* unknown suboption - catchall */
2385 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2386 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002389 }
2390 } /* end while loop */
2391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 else {
2393 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 }
Willy Tarreau93893792009-07-23 13:19:11 +02002397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002399 else if (!strcmp(args[0], "default_backend")) {
2400 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002402
2403 if (*(args[1]) == 0) {
2404 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002407 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002408 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002409 curproxy->defbe.name = strdup(args[1]);
2410 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002412 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002414
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002415 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2416 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 /* enable reconnections to dispatch */
2419 curproxy->options |= PR_O_REDISP;
2420 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002421 else if (!strcmp(args[0], "http-check")) {
2422 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002424
2425 if (strcmp(args[1], "disable-on-404") == 0) {
2426 /* enable a graceful server shutdown on an HTTP 404 response */
2427 curproxy->options |= PR_O_DISABLE404;
2428 }
2429 else {
2430 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002433 }
2434 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002435 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002436 if (curproxy == &defproxy) {
2437 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002440 }
2441
Willy Tarreaub80c2302007-11-30 20:51:32 +01002442 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002444
2445 if (strcmp(args[1], "fail") == 0) {
2446 /* add a condition to fail monitor requests */
2447 int pol = ACL_COND_NONE;
2448 struct acl_cond *cond;
2449
2450 if (!strcmp(args[2], "if"))
2451 pol = ACL_COND_IF;
2452 else if (!strcmp(args[2], "unless"))
2453 pol = ACL_COND_UNLESS;
2454
2455 if (pol == ACL_COND_NONE) {
2456 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2457 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002460 }
2461
2462 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2463 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2464 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002467 }
Willy Tarreau88922352009-10-04 22:02:50 +02002468 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002469 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002470 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002471 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2472 }
2473 else {
2474 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002477 }
2478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479#ifdef TPROXY
2480 else if (!strcmp(args[0], "transparent")) {
2481 /* enable transparent proxy connections */
2482 curproxy->options |= PR_O_TRANSP;
2483 }
2484#endif
2485 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002486 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 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 Tarreaubaaee002006-06-26 02:48:02 +02002493 }
2494 curproxy->maxconn = atol(args[1]);
2495 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002496 else if (!strcmp(args[0], "backlog")) { /* backlog */
2497 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002499
2500 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 Tarreauc73ce2b2008-01-06 10:55:10 +01002504 }
2505 curproxy->backlog = atol(args[1]);
2506 }
Willy Tarreau86034312006-12-29 00:10:33 +01002507 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002508 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002510
Willy Tarreau86034312006-12-29 00:10:33 +01002511 if (*(args[1]) == 0) {
2512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002515 }
2516 curproxy->fullconn = atol(args[1]);
2517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2519 if (*(args[1]) == 0) {
2520 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002524 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2525 if (err) {
2526 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2527 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002530 }
2531 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
2533 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2534 if (curproxy == &defproxy) {
2535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002539 else 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
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 if (strchr(args[1], ':') == NULL) {
2543 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 }
2547 curproxy->dispatch_addr = *str2sa(args[1]);
2548 }
2549 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002552
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002553 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002554 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2555 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002560 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2561 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2562 err_code |= ERR_WARN;
2563
2564 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2565 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2566 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2567 }
2568 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2569 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2570 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2571 }
2572 else {
2573 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002578 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002580 char *rport, *raddr;
2581 short realport = 0;
2582 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002584 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002589 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591
2592 if (!*args[2]) {
2593 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002598
2599 err = invalid_char(args[1]);
2600 if (err) {
2601 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2602 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002605 }
2606
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2608 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_ABORT;
2610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 }
2612
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002613 if (!defsrv) {
2614 /* the servers are linked backwards first */
2615 newsrv->next = curproxy->srv;
2616 curproxy->srv = newsrv;
2617 newsrv->proxy = curproxy;
2618 newsrv->conf.file = file;
2619 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002621 LIST_INIT(&newsrv->pendconns);
2622 do_check = 0;
2623 newsrv->state = SRV_RUNNING; /* early server setup */
2624 newsrv->last_change = now.tv_sec;
2625 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002627 /* several ways to check the port component :
2628 * - IP => port=+0, relative
2629 * - IP: => port=+0, relative
2630 * - IP:N => port=N, absolute
2631 * - IP:+N => port=+N, relative
2632 * - IP:-N => port=-N, relative
2633 */
2634 raddr = strdup(args[2]);
2635 rport = strchr(raddr, ':');
2636 if (rport) {
2637 *rport++ = 0;
2638 realport = atol(rport);
2639 if (!isdigit((unsigned char)*rport))
2640 newsrv->state |= SRV_MAPPORTS;
2641 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002643
2644 newsrv->addr = *str2sa(raddr);
2645 newsrv->addr.sin_port = htons(realport);
2646 free(raddr);
2647
2648 newsrv->check_port = curproxy->defsrv.check_port;
2649 newsrv->inter = curproxy->defsrv.inter;
2650 newsrv->fastinter = curproxy->defsrv.fastinter;
2651 newsrv->downinter = curproxy->defsrv.downinter;
2652 newsrv->rise = curproxy->defsrv.rise;
2653 newsrv->fall = curproxy->defsrv.fall;
2654 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2655 newsrv->minconn = curproxy->defsrv.minconn;
2656 newsrv->maxconn = curproxy->defsrv.maxconn;
2657 newsrv->slowstart = curproxy->defsrv.slowstart;
2658 newsrv->onerror = curproxy->defsrv.onerror;
2659 newsrv->consecutive_errors_limit
2660 = curproxy->defsrv.consecutive_errors_limit;
2661 newsrv->uweight = newsrv->iweight
2662 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002664 newsrv->curfd = -1; /* no health-check in progress */
2665 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002667 cur_arg = 3;
2668 } else {
2669 newsrv = &curproxy->defsrv;
2670 cur_arg = 1;
2671 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002672
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002674 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002675 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002676
2677 if (!*args[cur_arg + 1]) {
2678 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2679 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002682 }
2683
2684 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002685 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002686
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002687 if (newsrv->puid <= 0) {
2688 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002689 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002692 }
2693
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002694 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2695 if (node) {
2696 struct server *target = container_of(node, struct server, conf.id);
2697 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2698 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
2701 }
2702 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002703 cur_arg += 2;
2704 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002705 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 newsrv->cookie = strdup(args[cur_arg + 1]);
2707 newsrv->cklen = strlen(args[cur_arg + 1]);
2708 cur_arg += 2;
2709 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002710 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01002711 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2712 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2713 cur_arg += 2;
2714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002716 if (!*args[cur_arg + 1]) {
2717 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2718 file, linenum, args[cur_arg]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002724 if (newsrv->rise <= 0) {
2725 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2726 file, linenum, args[cur_arg]);
2727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
2729 }
2730
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 newsrv->health = newsrv->rise;
2732 cur_arg += 2;
2733 }
2734 else if (!strcmp(args[cur_arg], "fall")) {
2735 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002736
2737 if (!*args[cur_arg + 1]) {
2738 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2739 file, linenum, args[cur_arg]);
2740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
2742 }
2743
2744 if (newsrv->fall <= 0) {
2745 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2746 file, linenum, args[cur_arg]);
2747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
2750
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 cur_arg += 2;
2752 }
2753 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002754 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2755 if (err) {
2756 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2757 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002760 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002761 if (val <= 0) {
2762 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2763 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002766 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002767 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 cur_arg += 2;
2769 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002770 else if (!strcmp(args[cur_arg], "fastinter")) {
2771 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2772 if (err) {
2773 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2774 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002777 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002778 if (val <= 0) {
2779 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2780 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002783 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002784 newsrv->fastinter = val;
2785 cur_arg += 2;
2786 }
2787 else if (!strcmp(args[cur_arg], "downinter")) {
2788 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2789 if (err) {
2790 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2791 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002794 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002795 if (val <= 0) {
2796 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2797 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002800 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002801 newsrv->downinter = val;
2802 cur_arg += 2;
2803 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002804 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002805 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002806 cur_arg += 2;
2807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 else if (!strcmp(args[cur_arg], "port")) {
2809 newsrv->check_port = atol(args[cur_arg + 1]);
2810 cur_arg += 2;
2811 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002812 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813 newsrv->state |= SRV_BACKUP;
2814 cur_arg ++;
2815 }
2816 else if (!strcmp(args[cur_arg], "weight")) {
2817 int w;
2818 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002819 if (w < 0 || w > 256) {
2820 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002825 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 cur_arg += 2;
2827 }
2828 else if (!strcmp(args[cur_arg], "minconn")) {
2829 newsrv->minconn = atol(args[cur_arg + 1]);
2830 cur_arg += 2;
2831 }
2832 else if (!strcmp(args[cur_arg], "maxconn")) {
2833 newsrv->maxconn = atol(args[cur_arg + 1]);
2834 cur_arg += 2;
2835 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002836 else if (!strcmp(args[cur_arg], "maxqueue")) {
2837 newsrv->maxqueue = atol(args[cur_arg + 1]);
2838 cur_arg += 2;
2839 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002840 else if (!strcmp(args[cur_arg], "slowstart")) {
2841 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002842 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002843 if (err) {
2844 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2845 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002848 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002849 if (val <= 0) {
2850 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2851 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002854 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002855 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002856 cur_arg += 2;
2857 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002858 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002859
2860 if (!*args[cur_arg + 1]) {
2861 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2862 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002865 }
2866
2867 newsrv->trackit = strdup(args[cur_arg + 1]);
2868
2869 cur_arg += 2;
2870 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002871 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 global.maxsock++;
2873 do_check = 1;
2874 cur_arg += 1;
2875 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002876 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002877 if (!strcmp(args[cur_arg + 1], "none"))
2878 newsrv->observe = HANA_OBS_NONE;
2879 else if (!strcmp(args[cur_arg + 1], "layer4"))
2880 newsrv->observe = HANA_OBS_LAYER4;
2881 else if (!strcmp(args[cur_arg + 1], "layer7")) {
2882 if (curproxy->mode != PR_MODE_HTTP) {
2883 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
2884 file, linenum, args[cur_arg + 1]);
2885 err_code |= ERR_ALERT;
2886 }
2887 newsrv->observe = HANA_OBS_LAYER7;
2888 }
2889 else {
2890 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
2891 "'l4events', 'http-responses' but get '%s'\n",
2892 file, linenum, args[cur_arg], args[cur_arg + 1]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 cur_arg += 2;
2898 }
2899 else if (!strcmp(args[cur_arg], "on-error")) {
2900 if (!strcmp(args[cur_arg + 1], "fastinter"))
2901 newsrv->onerror = HANA_ONERR_FASTINTER;
2902 else if (!strcmp(args[cur_arg + 1], "fail-check"))
2903 newsrv->onerror = HANA_ONERR_FAILCHK;
2904 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
2905 newsrv->onerror = HANA_ONERR_SUDDTH;
2906 else if (!strcmp(args[cur_arg + 1], "mark-down"))
2907 newsrv->onerror = HANA_ONERR_MARKDWN;
2908 else {
2909 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
2910 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
2911 file, linenum, args[cur_arg], args[cur_arg + 1]);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
2916 cur_arg += 2;
2917 }
2918 else if (!strcmp(args[cur_arg], "error-limit")) {
2919 if (!*args[cur_arg + 1]) {
2920 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2921 file, linenum, args[cur_arg]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
2926 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
2927
2928 if (newsrv->consecutive_errors_limit <= 0) {
2929 Alert("parsing [%s:%d]: %s has to be > 0.\n",
2930 file, linenum, args[cur_arg]);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933 }
2934 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002935 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002936 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002938#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002939 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002940 file, linenum, "source", "usesrc");
2941#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002942 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002944#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 }
2948 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002949 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2950
2951 if (port_low != port_high) {
2952 int i;
2953 if (port_low <= 0 || port_low > 65535 ||
2954 port_high <= 0 || port_high > 65535 ||
2955 port_low > port_high) {
2956 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2957 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002960 }
2961 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2962 for (i = 0; i < newsrv->sport_range->size; i++)
2963 newsrv->sport_range->ports[i] = port_low + i;
2964 }
2965
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002967 while (*(args[cur_arg])) {
2968 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002969#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2970#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002971 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2972 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2973 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002976 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002977#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002978 if (!*args[cur_arg + 1]) {
2979 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2980 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002983 }
2984 if (!strcmp(args[cur_arg + 1], "client")) {
2985 newsrv->state |= SRV_TPROXY_CLI;
2986 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2987 newsrv->state |= SRV_TPROXY_CIP;
2988 } else {
2989 newsrv->state |= SRV_TPROXY_ADDR;
2990 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2991 }
2992 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002993#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002994 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002995#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002996 cur_arg += 2;
2997 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002998#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002999 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003000 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003003#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3004 } /* "usesrc" */
3005
3006 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3007#ifdef SO_BINDTODEVICE
3008 if (!*args[cur_arg + 1]) {
3009 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003013 }
3014 if (newsrv->iface_name)
3015 free(newsrv->iface_name);
3016
3017 newsrv->iface_name = strdup(args[cur_arg + 1]);
3018 newsrv->iface_len = strlen(newsrv->iface_name);
3019 global.last_checks |= LSTCHK_NETADM;
3020#else
3021 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3022 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003025#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003026 cur_arg += 2;
3027 continue;
3028 }
3029 /* this keyword in not an option of "source" */
3030 break;
3031 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003033 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003034 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3035 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003040 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003041 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 +01003042 file, linenum, newsrv->id);
3043 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003044 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 +01003045 file, linenum);
3046
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
3050 }
3051
3052 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003053 if (newsrv->trackit) {
3054 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3055 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003058 }
3059
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003060 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3061 newsrv->check_port = newsrv->check_addr.sin_port;
3062
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3064 newsrv->check_port = realport; /* by default */
3065 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003066 /* not yet valid, because no port was set on
3067 * the server either. We'll check if we have
3068 * a known port on the first listener.
3069 */
3070 struct listener *l;
3071 l = curproxy->listen;
3072 if (l) {
3073 int port;
3074 port = (l->addr.ss_family == AF_INET6)
3075 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3076 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3077 newsrv->check_port = port;
3078 }
3079 }
3080 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3082 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003086
3087 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 newsrv->state |= SRV_CHECKED;
3089 }
3090
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003091 if (!defsrv) {
3092 if (newsrv->state & SRV_BACKUP)
3093 curproxy->srv_bck++;
3094 else
3095 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003096
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003097 newsrv->prev_state = newsrv->state;
3098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 }
3100 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003101 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 int facility;
3103
3104 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3105 curproxy->logfac1 = global.logfac1;
3106 curproxy->logsrv1 = global.logsrv1;
3107 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003108 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 curproxy->logfac2 = global.logfac2;
3110 curproxy->logsrv2 = global.logsrv2;
3111 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003112 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 }
3114 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003115 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116
3117 facility = get_log_facility(args[2]);
3118 if (facility < 0) {
3119 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3120 exit(1);
3121 }
3122
3123 level = 7; /* max syslog level = debug */
3124 if (*(args[3])) {
3125 level = get_log_level(args[3]);
3126 if (level < 0) {
3127 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3128 exit(1);
3129 }
3130 }
3131
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003132 minlvl = 0; /* limit syslog level to this level (emerg) */
3133 if (*(args[4])) {
3134 minlvl = get_log_level(args[4]);
3135 if (level < 0) {
3136 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3137 exit(1);
3138 }
3139 }
3140
Robert Tsai81ae1952007-12-05 10:47:29 +01003141 if (args[1][0] == '/') {
3142 logsrv.u.addr.sa_family = AF_UNIX;
3143 logsrv.u.un = *str2sun(args[1]);
3144 } else {
3145 logsrv.u.addr.sa_family = AF_INET;
3146 logsrv.u.in = *str2sa(args[1]);
3147 if (!logsrv.u.in.sin_port) {
3148 logsrv.u.in.sin_port =
3149 htons(SYSLOG_PORT);
3150 }
3151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152
3153 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003154 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 curproxy->logfac1 = facility;
3156 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003157 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003160 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 curproxy->logfac2 = facility;
3162 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003163 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 }
3165 else {
3166 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 }
3170 }
3171 else {
3172 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3173 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 }
3177 }
3178 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003179 int cur_arg;
3180
Willy Tarreau977b8e42006-12-29 14:19:17 +01003181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003183
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003185 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3186 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003190
3191 /* we must first clear any optional default setting */
3192 curproxy->options &= ~PR_O_TPXY_MASK;
3193 free(curproxy->iface_name);
3194 curproxy->iface_name = NULL;
3195 curproxy->iface_len = 0;
3196
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 curproxy->source_addr = *str2sa(args[1]);
3198 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003199
3200 cur_arg = 2;
3201 while (*(args[cur_arg])) {
3202 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003203#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3204#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003205 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3206 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3207 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003210 }
3211#endif
3212 if (!*args[cur_arg + 1]) {
3213 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3214 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003217 }
3218
3219 if (!strcmp(args[cur_arg + 1], "client")) {
3220 curproxy->options |= PR_O_TPXY_CLI;
3221 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3222 curproxy->options |= PR_O_TPXY_CIP;
3223 } else {
3224 curproxy->options |= PR_O_TPXY_ADDR;
3225 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3226 }
3227 global.last_checks |= LSTCHK_NETADM;
3228#if !defined(CONFIG_HAP_LINUX_TPROXY)
3229 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003230#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003231#else /* no TPROXY support */
3232 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003233 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003236#endif
3237 cur_arg += 2;
3238 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003239 }
3240
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003241 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3242#ifdef SO_BINDTODEVICE
3243 if (!*args[cur_arg + 1]) {
3244 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003248 }
3249 if (curproxy->iface_name)
3250 free(curproxy->iface_name);
3251
3252 curproxy->iface_name = strdup(args[cur_arg + 1]);
3253 curproxy->iface_len = strlen(curproxy->iface_name);
3254 global.last_checks |= LSTCHK_NETADM;
3255#else
3256 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3257 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003260#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003261 cur_arg += 2;
3262 continue;
3263 }
3264 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3265 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003270 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3271 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3272 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3277 regex_t *preg;
3278 if (curproxy == &defproxy) {
3279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003283 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003285
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 if (*(args[1]) == 0 || *(args[2]) == 0) {
3287 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
3292
3293 preg = calloc(1, sizeof(regex_t));
3294 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3295 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
3299
3300 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3301 if (err) {
3302 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3303 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003306 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
3308 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3309 regex_t *preg;
3310 if (curproxy == &defproxy) {
3311 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003315 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003317
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 if (*(args[1]) == 0) {
3319 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
3323
3324 preg = calloc(1, sizeof(regex_t));
3325 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3326 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3330
3331 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003332 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
3334 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3335 regex_t *preg;
3336 if (curproxy == &defproxy) {
3337 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003341 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003343
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 if (*(args[1]) == 0) {
3345 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
3349
3350 preg = calloc(1, sizeof(regex_t));
3351 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3352 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3356
3357 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003358 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
3360 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3361 regex_t *preg;
3362 if (curproxy == &defproxy) {
3363 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003367 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003369
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 if (*(args[1]) == 0) {
3371 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
3375
3376 preg = calloc(1, sizeof(regex_t));
3377 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3378 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3382
3383 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003384 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
3386 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3387 regex_t *preg;
3388 if (curproxy == &defproxy) {
3389 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003393 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003395
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 if (*(args[1]) == 0) {
3397 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
3401
3402 preg = calloc(1, sizeof(regex_t));
3403 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3404 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 }
3408
3409 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003410 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003412 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3413 regex_t *preg;
3414 if (curproxy == &defproxy) {
3415 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003418 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003419 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003420 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003421
Willy Tarreaub8750a82006-09-03 09:56:00 +02003422 if (*(args[1]) == 0) {
3423 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003426 }
3427
3428 preg = calloc(1, sizeof(regex_t));
3429 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3430 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003433 }
3434
3435 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003436 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003437 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003438 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3439 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003440 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003444 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003445 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003446 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003447
Willy Tarreau977b8e42006-12-29 14:19:17 +01003448 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003449 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003453 }
3454
3455 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003456 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003457 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3461
3462 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003463 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003464 }
3465 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3466 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003467 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003468 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003471 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003472 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003473 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003474
Willy Tarreau977b8e42006-12-29 14:19:17 +01003475 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003476 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3477 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003480 }
3481
3482 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003483 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003484 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003487 }
3488
3489 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003490 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3493 regex_t *preg;
3494 if (curproxy == &defproxy) {
3495 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003499 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003501
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 if (*(args[1]) == 0 || *(args[2]) == 0) {
3503 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3504 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 }
3508
3509 preg = calloc(1, sizeof(regex_t));
3510 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3511 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 }
3515
3516 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3517 if (err) {
3518 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3519 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_FATAL;
3521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003523 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
3525 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3526 regex_t *preg;
3527 if (curproxy == &defproxy) {
3528 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003532 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003533 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003534
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 if (*(args[1]) == 0) {
3536 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }
3540
3541 preg = calloc(1, sizeof(regex_t));
3542 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3543 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3547
3548 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003549 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 }
3551 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3552 regex_t *preg;
3553 if (curproxy == &defproxy) {
3554 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003558 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003560
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 if (*(args[1]) == 0) {
3562 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
3566
3567 preg = calloc(1, sizeof(regex_t));
3568 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3569 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
3573
3574 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003575 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 }
3577 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3578 regex_t *preg;
3579 if (curproxy == &defproxy) {
3580 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003584 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003586
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 if (*(args[1]) == 0) {
3588 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
3592
3593 preg = calloc(1, sizeof(regex_t));
3594 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3595 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
3599
3600 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003601 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 }
3603 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3604 regex_t *preg;
3605 if (curproxy == &defproxy) {
3606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003610 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003612
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 if (*(args[1]) == 0) {
3614 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
3618
3619 preg = calloc(1, sizeof(regex_t));
3620 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3621 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 }
3625
3626 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003627 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003629 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3630 regex_t *preg;
3631 if (curproxy == &defproxy) {
3632 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003635 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003636 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003638
Willy Tarreaub8750a82006-09-03 09:56:00 +02003639 if (*(args[1]) == 0) {
3640 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003643 }
3644
3645 preg = calloc(1, sizeof(regex_t));
3646 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3647 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003650 }
3651
3652 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003653 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003656 struct wordlist *wl;
3657
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 if (curproxy == &defproxy) {
3659 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003663 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 if (*(args[1]) == 0) {
3667 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003671
3672 wl = calloc(1, sizeof(*wl));
3673 wl->s = strdup(args[1]);
3674 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003675 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 }
3677 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3678 regex_t *preg;
3679
3680 if (*(args[1]) == 0 || *(args[2]) == 0) {
3681 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003686 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003688
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 preg = calloc(1, sizeof(regex_t));
3690 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3691 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 }
3695
3696 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3697 if (err) {
3698 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3699 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003703 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
3705 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3706 regex_t *preg;
3707 if (curproxy == &defproxy) {
3708 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003712 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003714
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 if (*(args[1]) == 0) {
3716 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
3720
3721 preg = calloc(1, sizeof(regex_t));
3722 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3723 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 }
3727
3728 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3729 if (err) {
3730 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3731 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 }
3735 }
3736 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3737 regex_t *preg;
3738 if (curproxy == &defproxy) {
3739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003743 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003745
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 if (*(args[1]) == 0) {
3747 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 }
3751
3752 preg = calloc(1, sizeof(regex_t));
3753 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3754 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 }
3758
3759 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3760 if (err) {
3761 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3762 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 }
3766 }
3767 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3768 regex_t *preg;
3769 if (curproxy == &defproxy) {
3770 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776
3777 if (*(args[1]) == 0 || *(args[2]) == 0) {
3778 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3779 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 }
3783
3784 preg = calloc(1, sizeof(regex_t));
3785 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3786 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
3790
3791 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3792 if (err) {
3793 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3794 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003797 }
3798 }
3799 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3800 regex_t *preg;
3801 if (curproxy == &defproxy) {
3802 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003806 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003808
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 if (*(args[1]) == 0) {
3810 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
3814
3815 preg = calloc(1, sizeof(regex_t));
3816 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3817 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 }
3821
3822 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3823 if (err) {
3824 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3825 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 }
3829 }
3830 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3831 regex_t *preg;
3832 if (curproxy == &defproxy) {
3833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003837 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003839
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 if (*(args[1]) == 0) {
3841 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
3845
3846 preg = calloc(1, sizeof(regex_t));
3847 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3848 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
3852
3853 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3854 if (err) {
3855 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3856 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
3860 }
3861 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003862 struct wordlist *wl;
3863
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 if (curproxy == &defproxy) {
3865 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003869 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 if (*(args[1]) == 0) {
3873 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
3877
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003878 wl = calloc(1, sizeof(*wl));
3879 wl->s = strdup(args[1]);
3880 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 }
3882 else if (!strcmp(args[0], "errorloc") ||
3883 !strcmp(args[0], "errorloc302") ||
3884 !strcmp(args[0], "errorloc303")) { /* error location */
3885 int errnum, errlen;
3886 char *err;
3887
Willy Tarreau977b8e42006-12-29 14:19:17 +01003888 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003890
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003892 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895 }
3896
3897 errnum = atol(args[1]);
3898 if (!strcmp(args[0], "errorloc303")) {
3899 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3900 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3901 } else {
3902 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3903 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3904 }
3905
Willy Tarreau0f772532006-12-23 20:51:41 +01003906 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3907 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003908 chunk_destroy(&curproxy->errmsg[rc]);
3909 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003910 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003913
3914 if (rc >= HTTP_ERR_SIZE) {
3915 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3916 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 free(err);
3918 }
3919 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003920 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3921 int errnum, errlen, fd;
3922 char *err;
3923 struct stat stat;
3924
3925 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003927
3928 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003929 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003932 }
3933
3934 fd = open(args[2], O_RDONLY);
3935 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3936 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3937 file, linenum, args[2], args[1]);
3938 if (fd >= 0)
3939 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003942 }
3943
Willy Tarreau27a674e2009-08-17 07:23:33 +02003944 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003945 errlen = stat.st_size;
3946 } else {
3947 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003948 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003950 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003951 }
3952
3953 err = malloc(errlen); /* malloc() must succeed during parsing */
3954 errnum = read(fd, err, errlen);
3955 if (errnum != errlen) {
3956 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3957 file, linenum, args[2], args[1]);
3958 close(fd);
3959 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003962 }
3963 close(fd);
3964
3965 errnum = atol(args[1]);
3966 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3967 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003968 chunk_destroy(&curproxy->errmsg[rc]);
3969 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003970 break;
3971 }
3972 }
3973
3974 if (rc >= HTTP_ERR_SIZE) {
3975 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3976 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003978 free(err);
3979 }
3980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003982 struct cfg_kw_list *kwl;
3983 int index;
3984
3985 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3986 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3987 if (kwl->kw[index].section != CFG_LISTEN)
3988 continue;
3989 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3990 /* prepare error message just in case */
3991 snprintf(trash, sizeof(trash),
3992 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003993 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3994 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003995 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003998 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003999 else if (rc > 0) {
4000 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_WARN;
4002 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004003 }
Willy Tarreau93893792009-07-23 13:19:11 +02004004 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004005 }
4006 }
4007 }
4008
Willy Tarreau6daf3432008-01-22 16:44:08 +01004009 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 }
Willy Tarreau93893792009-07-23 13:19:11 +02004013 out:
4014 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015}
4016
4017
4018/*
4019 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004020 * Returns the error code, 0 if OK, or any combination of :
4021 * - ERR_ABORT: must abort ASAP
4022 * - ERR_FATAL: we can continue parsing but not start the service
4023 * - ERR_WARN: a warning has been emitted
4024 * - ERR_ALERT: an alert has been emitted
4025 * Only the two first ones can stop processing, the two others are just
4026 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004028int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004030 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 FILE *f;
4032 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004034 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 if ((f=fopen(file,"r")) == NULL)
4037 return -1;
4038
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004039 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004040 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004041 char *end;
4042 char *args[MAX_LINE_ARGS + 1];
4043 char *line = thisline;
4044
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 linenum++;
4046
4047 end = line + strlen(line);
4048
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004049 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4050 /* Check if we reached the limit and the last char is not \n.
4051 * Watch out for the last line without the terminating '\n'!
4052 */
4053 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004054 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004056 }
4057
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004059 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 line++;
4061
4062 arg = 0;
4063 args[arg] = line;
4064
4065 while (*line && arg < MAX_LINE_ARGS) {
4066 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4067 * C equivalent value. Other combinations left unchanged (eg: \1).
4068 */
4069 if (*line == '\\') {
4070 int skip = 0;
4071 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4072 *line = line[1];
4073 skip = 1;
4074 }
4075 else if (line[1] == 'r') {
4076 *line = '\r';
4077 skip = 1;
4078 }
4079 else if (line[1] == 'n') {
4080 *line = '\n';
4081 skip = 1;
4082 }
4083 else if (line[1] == 't') {
4084 *line = '\t';
4085 skip = 1;
4086 }
4087 else if (line[1] == 'x') {
4088 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
4089 unsigned char hex1, hex2;
4090 hex1 = toupper(line[2]) - '0';
4091 hex2 = toupper(line[3]) - '0';
4092 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4093 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4094 *line = (hex1<<4) + hex2;
4095 skip = 3;
4096 }
4097 else {
4098 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 }
4101 }
4102 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004103 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 end -= skip;
4105 }
4106 line++;
4107 }
4108 else if (*line == '#' || *line == '\n' || *line == '\r') {
4109 /* end of string, end of loop */
4110 *line = 0;
4111 break;
4112 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004113 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004115 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004116 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117 line++;
4118 args[++arg] = line;
4119 }
4120 else {
4121 line++;
4122 }
4123 }
4124
4125 /* empty line */
4126 if (!**args)
4127 continue;
4128
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004129 if (*line) {
4130 /* we had to stop due to too many args.
4131 * Let's terminate the string, print the offending part then cut the
4132 * last arg.
4133 */
4134 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4135 line++;
4136 *line = '\0';
4137
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004138 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004139 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 args[arg] = line;
4142 }
4143
Willy Tarreau540abe42007-05-02 20:50:16 +02004144 /* zero out remaining args and ensure that at least one entry
4145 * is zeroed out.
4146 */
4147 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 args[arg] = line;
4149 }
4150
Willy Tarreau3842f002009-06-14 11:39:52 +02004151 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004152 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004153 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004154 for (arg=0; *args[arg+1]; arg++)
4155 args[arg] = args[arg+1]; // shift args after inversion
4156 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004157 else if (!strcmp(args[0], "default")) {
4158 kwm = KWM_DEF;
4159 for (arg=0; *args[arg+1]; arg++)
4160 args[arg] = args[arg+1]; // shift args after inversion
4161 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004162
Willy Tarreau3842f002009-06-14 11:39:52 +02004163 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4164 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004166 }
4167
Willy Tarreau977b8e42006-12-29 14:19:17 +01004168 if (!strcmp(args[0], "listen") ||
4169 !strcmp(args[0], "frontend") ||
4170 !strcmp(args[0], "backend") ||
4171 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004172 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004174 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004175 cursection = strdup(args[0]);
4176 }
4177 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004179 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004180 cursection = strdup(args[0]);
4181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 /* else it's a section keyword */
4183
4184 switch (confsect) {
4185 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 break;
4188 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004189 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 break;
4191 default:
4192 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004195
4196 if (err_code & ERR_ABORT)
4197 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004199 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004200 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004201 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004202 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004203}
4204
Willy Tarreaubb925012009-07-23 13:36:36 +02004205/*
4206 * Returns the error code, 0 if OK, or any combination of :
4207 * - ERR_ABORT: must abort ASAP
4208 * - ERR_FATAL: we can continue parsing but not start the service
4209 * - ERR_WARN: a warning has been emitted
4210 * - ERR_ALERT: an alert has been emitted
4211 * Only the two first ones can stop processing, the two others are just
4212 * indicators.
4213 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004214int check_config_validity()
4215{
4216 int cfgerr = 0;
4217 struct proxy *curproxy = NULL;
4218 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004219 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004220 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221
4222 /*
4223 * Now, check for the integrity of all that we have collected.
4224 */
4225
4226 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004227 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004229 /* first, we will invert the proxy list order */
4230 curproxy = NULL;
4231 while (proxy) {
4232 struct proxy *next;
4233
4234 next = proxy->next;
4235 proxy->next = curproxy;
4236 curproxy = proxy;
4237 if (!next)
4238 break;
4239 proxy = next;
4240 }
4241
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004243 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004244 err_code |= ERR_ALERT | ERR_FATAL;
4245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 }
4247
4248 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004249 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004250 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004251 unsigned int next_id;
4252
4253 if (!curproxy->uuid) {
4254 /* proxy ID not set, use automatic numbering with first
4255 * spare entry starting with next_pxid.
4256 */
4257 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4258 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4259 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4260 next_pxid++;
4261 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004262
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004264 /* ensure we don't keep listeners uselessly bound */
4265 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004266 curproxy = curproxy->next;
4267 continue;
4268 }
4269
Willy Tarreauff01a212009-03-15 13:46:16 +01004270 switch (curproxy->mode) {
4271 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004272 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004273 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004274 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4275 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004276 cfgerr++;
4277 }
4278
4279 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004280 Warning("config : servers will be ignored for %s '%s'.\n",
4281 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004282 break;
4283
4284 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004285 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004286 break;
4287
4288 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004289 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004290 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004291 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4292 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004293 cfgerr++;
4294 }
4295 break;
4296 }
4297
4298 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004299 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4300 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 cfgerr++;
4302 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004303
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004304 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004305 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004306 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004307 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4308 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004309 cfgerr++;
4310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004312 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004313 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4314 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004315 cfgerr++;
4316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004318 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004319 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4320 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004321 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004322 }
4323 }
4324 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4325 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4326 /* If no LB algo is set in a backend, and we're not in
4327 * transparent mode, dispatch mode nor proxy mode, we
4328 * want to use balance roundrobin by default.
4329 */
4330 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4331 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 }
4333 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004334
Willy Tarreau82936582007-11-30 15:20:09 +01004335 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4336 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004337 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4338 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004339 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004340 }
4341
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004342 /* if a default backend was specified, let's find it */
4343 if (curproxy->defbe.name) {
4344 struct proxy *target;
4345
Alex Williams96532db2009-11-01 21:27:13 -05004346 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004347 if (!target) {
4348 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4349 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004350 cfgerr++;
4351 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004352 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4353 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004354 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004355 } else {
4356 free(curproxy->defbe.name);
4357 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004358 /* we force the backend to be present on at least all of
4359 * the frontend's processes.
4360 */
4361 target->bind_proc = curproxy->bind_proc ?
4362 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 }
4364 }
4365
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004366 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004367 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4368 /* map jump target for ACT_SETBE in req_rep chain */
4369 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004370 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004371 struct proxy *target;
4372
Willy Tarreaua496b602006-12-17 23:15:24 +01004373 if (exp->action != ACT_SETBE)
4374 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004375
Alex Williams96532db2009-11-01 21:27:13 -05004376 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004377 if (!target) {
4378 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4379 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004380 cfgerr++;
4381 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004382 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4383 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004384 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004385 } else {
4386 free((void *)exp->replace);
4387 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004388 /* we force the backend to be present on at least all of
4389 * the frontend's processes.
4390 */
4391 target->bind_proc = curproxy->bind_proc ?
4392 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004393 }
4394 }
4395 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004396
4397 /* find the target proxy for 'use_backend' rules */
4398 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004399 struct proxy *target;
4400
Alex Williams96532db2009-11-01 21:27:13 -05004401 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004402
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004403 if (!target) {
4404 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4405 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004406 cfgerr++;
4407 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004408 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4409 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004410 cfgerr++;
4411 } else {
4412 free((void *)rule->be.name);
4413 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004414 /* we force the backend to be present on at least all of
4415 * the frontend's processes.
4416 */
4417 target->bind_proc = curproxy->bind_proc ?
4418 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004419 }
4420 }
4421
Willy Tarreau2738a142006-07-08 17:28:09 +02004422 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004423 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004424 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004425 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004426 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004427 " | While not properly invalid, you will certainly encounter various problems\n"
4428 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004429 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004430 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004431 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004432 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004433
Willy Tarreau1fa31262007-12-03 00:36:16 +01004434 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4435 * We must still support older configurations, so let's find out whether those
4436 * parameters have been set or must be copied from contimeouts.
4437 */
4438 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004439 if (!curproxy->timeout.tarpit ||
4440 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004441 /* tarpit timeout not set. We search in the following order:
4442 * default.tarpit, curr.connect, default.connect.
4443 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004444 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004445 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004446 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004447 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004448 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004449 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004450 }
4451 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004452 (!curproxy->timeout.queue ||
4453 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004454 /* queue timeout not set. We search in the following order:
4455 * default.queue, curr.connect, default.connect.
4456 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004457 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004458 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004459 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004460 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004461 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004462 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004463 }
4464 }
4465
Willy Tarreauf3c69202006-07-09 16:42:34 +02004466 if (curproxy->options & PR_O_SSL3_CHK) {
4467 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4468 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4469 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4470 }
4471
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004472 /* The small pools required for the capture lists */
4473 if (curproxy->nb_req_cap)
4474 curproxy->req_cap_pool = create_pool("ptrcap",
4475 curproxy->nb_req_cap * sizeof(char *),
4476 MEM_F_SHARED);
4477 if (curproxy->nb_rsp_cap)
4478 curproxy->rsp_cap_pool = create_pool("ptrcap",
4479 curproxy->nb_rsp_cap * sizeof(char *),
4480 MEM_F_SHARED);
4481
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004482 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4483 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4484 MEM_F_SHARED);
4485
Willy Tarreau86034312006-12-29 00:10:33 +01004486 /* for backwards compatibility with "listen" instances, if
4487 * fullconn is not set but maxconn is set, then maxconn
4488 * is used.
4489 */
4490 if (!curproxy->fullconn)
4491 curproxy->fullconn = curproxy->maxconn;
4492
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 /* first, we will invert the servers list order */
4494 newsrv = NULL;
4495 while (curproxy->srv) {
4496 struct server *next;
4497
4498 next = curproxy->srv->next;
4499 curproxy->srv->next = newsrv;
4500 newsrv = curproxy->srv;
4501 if (!next)
4502 break;
4503 curproxy->srv = next;
4504 }
4505
Willy Tarreau20697042007-11-15 23:26:18 +01004506 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004507 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004509 /* We have to initialize the server lookup mechanism depending
4510 * on what LB algorithm was choosen.
4511 */
4512
4513 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4514 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4515 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004516 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4517 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4518 init_server_map(curproxy);
4519 } else {
4520 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4521 fwrr_init_server_groups(curproxy);
4522 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004523 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004524
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004525 case BE_LB_KIND_LC:
4526 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004527 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004528 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004529
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004530 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004531 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4532 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4533 chash_init_server_tree(curproxy);
4534 } else {
4535 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4536 init_server_map(curproxy);
4537 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004538 break;
4539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540
4541 if (curproxy->options & PR_O_LOGASAP)
4542 curproxy->to_log &= ~LW_BYTES;
4543
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004544 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4545 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4546 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4547 proxy_type_str(curproxy), curproxy->id);
4548 err_code |= ERR_WARN;
4549 }
4550
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004552 * ensure that we're not cross-dressing a TCP server into HTTP.
4553 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004554 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004555 newsrv = curproxy->srv;
4556 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004557 if (!newsrv->puid) {
4558 /* server ID not set, use automatic numbering with first
4559 * spare entry starting with next_svid.
4560 */
4561 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4562 newsrv->conf.id.key = newsrv->puid = next_id;
4563 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4564 next_id++;
4565 }
4566
Willy Tarreau21d2af32008-02-14 20:25:24 +01004567 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004568 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4569 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004570 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004571 }
4572 newsrv = newsrv->next;
4573 }
4574
4575 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 * If this server supports a maxconn parameter, it needs a dedicated
4577 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004578 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 */
4580 newsrv = curproxy->srv;
4581 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004582 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 /* Only 'minconn' was specified, or it was higher than or equal
4584 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4585 * this will avoid further useless expensive computations.
4586 */
4587 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004588 } else if (newsrv->maxconn && !newsrv->minconn) {
4589 /* minconn was not specified, so we set it to maxconn */
4590 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004591 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004592 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4593 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004594 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004597 if (newsrv->trackit) {
4598 struct proxy *px;
4599 struct server *srv;
4600 char *pname, *sname;
4601
4602 pname = newsrv->trackit;
4603 sname = strrchr(pname, '/');
4604
4605 if (sname)
4606 *sname++ = '\0';
4607 else {
4608 sname = pname;
4609 pname = NULL;
4610 }
4611
4612 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004613 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004614 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004615 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4616 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004617 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004618 cfgerr++;
4619 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004620 }
4621 } else
4622 px = curproxy;
4623
4624 srv = findserver(px, sname);
4625 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004626 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4627 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004628 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004629 cfgerr++;
4630 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004631 }
4632
4633 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004634 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004635 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004636 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004637 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004638 cfgerr++;
4639 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004640 }
4641
4642 if (curproxy != px &&
4643 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004644 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004645 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004646 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004647 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004648 cfgerr++;
4649 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004650 }
4651
4652 newsrv->tracked = srv;
4653 newsrv->tracknext = srv->tracknext;
4654 srv->tracknext = newsrv;
4655
4656 free(newsrv->trackit);
4657 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004658 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 newsrv = newsrv->next;
4660 }
4661
Willy Tarreauc1a21672009-08-16 22:37:44 +02004662 if (curproxy->cap & PR_CAP_FE) {
4663 if (curproxy->tcp_req.inspect_delay ||
4664 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4665 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4666
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004667 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004668 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004669 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004670 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004671
4672 /* both TCP and HTTP must check switching rules */
4673 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4674 }
4675
4676 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004677 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004678 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004679 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004680 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004681
4682 /* If the backend does requires RDP cookie persistence, we have to
4683 * enable the corresponding analyser.
4684 */
4685 if (curproxy->options2 & PR_O2_RDPC_PRST)
4686 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4687 }
4688
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004689 listener = NULL;
4690 while (curproxy->listen) {
4691 struct listener *next;
4692
4693 next = curproxy->listen->next;
4694 curproxy->listen->next = listener;
4695 listener = curproxy->listen;
4696
4697 if (!next)
4698 break;
4699
4700 curproxy->listen = next;
4701 }
4702
Willy Tarreaue6b98942007-10-29 01:09:36 +01004703 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004704 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004705 listener = curproxy->listen;
4706 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004707 if (!listener->luid) {
4708 /* listener ID not set, use automatic numbering with first
4709 * spare entry starting with next_luid.
4710 */
4711 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4712 listener->conf.id.key = listener->luid = next_id;
4713 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4714 next_id++;
4715 }
4716
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004717 /* enable separate counters */
4718 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4719 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4720 if (!listener->name) {
4721 sprintf(trash, "sock-%d", listener->luid);
4722 listener->name = strdup(trash);
4723 }
4724 }
4725
Willy Tarreaue6b98942007-10-29 01:09:36 +01004726 if (curproxy->options & PR_O_TCP_NOLING)
4727 listener->options |= LI_O_NOLINGER;
4728 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004729 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004730 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004731 listener->accept = event_accept;
4732 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004733 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004734 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004735
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004736 /* smart accept mode is automatic in HTTP mode */
4737 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4738 (curproxy->mode == PR_MODE_HTTP &&
4739 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4740 listener->options |= LI_O_NOQUICKACK;
4741
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004742 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004743 listener = listener->next;
4744 }
4745
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 curproxy = curproxy->next;
4747 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004748
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004749 /*
4750 * Recount currently required checks.
4751 */
4752
4753 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4754 int optnum;
4755
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004756 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4757 if (curproxy->options & cfg_opts[optnum].val)
4758 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004759
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004760 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4761 if (curproxy->options2 & cfg_opts2[optnum].val)
4762 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004763 }
4764
Willy Tarreaubb925012009-07-23 13:36:36 +02004765 if (cfgerr > 0)
4766 err_code |= ERR_ALERT | ERR_FATAL;
4767 out:
4768 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769}
4770
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004771/*
4772 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4773 * parsing sessions.
4774 */
4775void cfg_register_keywords(struct cfg_kw_list *kwl)
4776{
4777 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4778}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004780/*
4781 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4782 */
4783void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4784{
4785 LIST_DEL(&kwl->list);
4786 LIST_INIT(&kwl->list);
4787}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004788
4789/*
4790 * Local variables:
4791 * c-indent-level: 8
4792 * c-basic-offset: 8
4793 * End:
4794 */