blob: 893e16e936e14f1d8f6e7f2ad9747f851e96093c [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 Tarreau977b8e42006-12-29 14:19:17 +01001009 curproxy->uri_auth = defproxy.uri_auth;
1010 curproxy->mon_net = defproxy.mon_net;
1011 curproxy->mon_mask = defproxy.mon_mask;
1012 if (defproxy.monitor_uri)
1013 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1014 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001015 if (defproxy.defbe.name)
1016 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001017 }
1018
1019 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001020 curproxy->timeout.connect = defproxy.timeout.connect;
1021 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001022 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001023 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001024 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001025 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001026 curproxy->source_addr = defproxy.source_addr;
1027 }
1028
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 curproxy->mode = defproxy.mode;
1030 curproxy->logfac1 = defproxy.logfac1;
1031 curproxy->logsrv1 = defproxy.logsrv1;
1032 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001033 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 curproxy->logfac2 = defproxy.logfac2;
1035 curproxy->logsrv2 = defproxy.logsrv2;
1036 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001037 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001039 curproxy->conf.used_listener_id = EB_ROOT;
1040 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001041
Willy Tarreau93893792009-07-23 13:19:11 +02001042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 }
1044 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1045 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001046 /* FIXME-20070101: we should do this too at the end of the
1047 * config parsing to free all default values.
1048 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001049 free(defproxy.check_req);
1050 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001051 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001052 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001053 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001054 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001055 free(defproxy.capture_name);
1056 free(defproxy.monitor_uri);
1057 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001058 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001059 free(defproxy.fwdfor_hdr_name);
1060 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001061 free(defproxy.orgto_hdr_name);
1062 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001063
Willy Tarreaua534fea2008-08-03 12:19:50 +02001064 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001065 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001066
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 /* we cannot free uri_auth because it might already be used */
1068 init_default_instance();
1069 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001070 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 else if (curproxy == NULL) {
1074 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
1078
Willy Tarreau977b8e42006-12-29 14:19:17 +01001079
1080 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001082 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001083 int cur_arg;
1084
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 if (curproxy == &defproxy) {
1086 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001090 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001091 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092
1093 if (strchr(args[1], ':') == NULL) {
1094 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001099
1100 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001101 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
1104 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001105
Willy Tarreau90a570f2009-10-04 20:54:54 +02001106 new_listen = curproxy->listen;
1107 while (new_listen != last_listen) {
1108 new_listen->conf.file = file;
1109 new_listen->conf.line = linenum;
1110 new_listen = new_listen->next;
1111 }
1112
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001113 cur_arg = 2;
1114 while (*(args[cur_arg])) {
1115 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1116#ifdef SO_BINDTODEVICE
1117 struct listener *l;
1118
1119 if (!*args[cur_arg + 1]) {
1120 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1121 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001124 }
1125
1126 for (l = curproxy->listen; l != last_listen; l = l->next)
1127 l->interface = strdup(args[cur_arg + 1]);
1128
1129 global.last_checks |= LSTCHK_NETADM;
1130
1131 cur_arg += 2;
1132 continue;
1133#else
1134 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1135 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
1137 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001138#endif
1139 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001140 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1141#ifdef TCP_MAXSEG
1142 struct listener *l;
1143 int mss;
1144
1145 if (!*args[cur_arg + 1]) {
1146 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1147 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001150 }
1151
1152 mss = str2uic(args[cur_arg + 1]);
1153 if (mss < 1 || mss > 65535) {
1154 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001158 }
1159
1160 for (l = curproxy->listen; l != last_listen; l = l->next)
1161 l->maxseg = mss;
1162
1163 cur_arg += 2;
1164 continue;
1165#else
1166 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1167 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001168 err_code |= ERR_ALERT | ERR_FATAL;
1169 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001170#endif
1171 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001172
1173 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1174#ifdef TCP_DEFER_ACCEPT
1175 struct listener *l;
1176
1177 for (l = curproxy->listen; l != last_listen; l = l->next)
1178 l->options |= LI_O_DEF_ACCEPT;
1179
1180 cur_arg ++;
1181 continue;
1182#else
1183 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1184 file, linenum, args[0], args[cur_arg]);
1185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto out;
1187#endif
1188 }
1189
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001190 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001191#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001192 struct listener *l;
1193
1194 for (l = curproxy->listen; l != last_listen; l = l->next)
1195 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001196
1197 cur_arg ++;
1198 continue;
1199#else
1200 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1201 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001202 err_code |= ERR_ALERT | ERR_FATAL;
1203 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001204#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001205 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001206
1207 if (!strcmp(args[cur_arg], "name")) {
1208 struct listener *l;
1209
1210 for (l = curproxy->listen; l != last_listen; l = l->next)
1211 l->name = strdup(args[cur_arg + 1]);
1212
1213 cur_arg += 2;
1214 continue;
1215 }
1216
1217 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001218 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001219 struct listener *l;
1220
1221 if (curproxy->listen->next != last_listen) {
1222 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1223 file, linenum, args[cur_arg]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227
1228 if (!*args[cur_arg + 1]) {
1229 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1230 file, linenum, args[cur_arg]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234
1235 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001236 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001237
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001238 if (curproxy->listen->luid <= 0) {
1239 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001240 file, linenum);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001245 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1246 if (node) {
1247 l = container_of(node, struct listener, conf.id);
1248 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1249 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1254
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001255 cur_arg += 2;
1256 continue;
1257 }
1258
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001259 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 +01001260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 }
1267 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1268 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1269 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1270 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001274 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001275 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001276
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 /* flush useless bits */
1278 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001281 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001282 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001283 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001284
Willy Tarreau1c47f852006-07-09 08:22:27 +02001285 if (!*args[1]) {
1286 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1287 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001290 }
1291
Willy Tarreaua534fea2008-08-03 12:19:50 +02001292 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001293 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001294 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001295 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001296 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1297
Willy Tarreau93893792009-07-23 13:19:11 +02001298 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1301 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1302 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1303 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1304 else {
1305 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001306 err_code |= ERR_ALERT | ERR_FATAL;
1307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 }
1309 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001310 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001311 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001312
1313 if (curproxy == &defproxy) {
1314 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1315 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001318 }
1319
1320 if (!*args[1]) {
1321 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1322 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001325 }
1326
1327 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001328 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001329
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001330 if (curproxy->uuid <= 0) {
1331 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001332 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001333 err_code |= ERR_ALERT | ERR_FATAL;
1334 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001335 }
1336
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001337 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1338 if (node) {
1339 struct proxy *target = container_of(node, struct proxy, conf.id);
1340 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1341 file, linenum, proxy_type_str(curproxy), curproxy->id,
1342 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
1345 }
1346 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001347 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001348 else if (!strcmp(args[0], "description")) {
1349 int i, len=0;
1350 char *d;
1351
1352 if (!*args[1]) {
1353 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1354 file, linenum, args[0]);
1355 return -1;
1356 }
1357
1358 for(i=1; *args[i]; i++)
1359 len += strlen(args[i])+1;
1360
1361 d = (char *)calloc(1, len);
1362 curproxy->desc = d;
1363
1364 d += sprintf(d, "%s", args[1]);
1365 for(i=2; *args[i]; i++)
1366 d += sprintf(d, " %s", args[i]);
1367
1368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1370 curproxy->state = PR_STSTOPPED;
1371 }
1372 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1373 curproxy->state = PR_STNEW;
1374 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001375 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1376 int cur_arg = 1;
1377 unsigned int set = 0;
1378
1379 while (*args[cur_arg]) {
1380 int u;
1381 if (strcmp(args[cur_arg], "all") == 0) {
1382 set = 0;
1383 break;
1384 }
1385 else if (strcmp(args[cur_arg], "odd") == 0) {
1386 set |= 0x55555555;
1387 }
1388 else if (strcmp(args[cur_arg], "even") == 0) {
1389 set |= 0xAAAAAAAA;
1390 }
1391 else {
1392 u = str2uic(args[cur_arg]);
1393 if (u < 1 || u > 32) {
1394 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001396 err_code |= ERR_ALERT | ERR_FATAL;
1397 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001398 }
1399 if (u > global.nbproc) {
1400 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1401 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001402 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001403 }
1404 set |= 1 << (u - 1);
1405 }
1406 cur_arg++;
1407 }
1408 curproxy->bind_proc = set;
1409 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001410 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001411 if (curproxy == &defproxy) {
1412 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001415 }
1416
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001417 err = invalid_char(args[1]);
1418 if (err) {
1419 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1420 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001421 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001422 }
1423
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001424 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1425 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1426 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001427 err_code |= ERR_ALERT | ERR_FATAL;
1428 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001429 }
1430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1432 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433
Willy Tarreau977b8e42006-12-29 14:19:17 +01001434 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001435 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001436
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 if (*(args[1]) == 0) {
1438 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001443
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001444 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001445 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 curproxy->cookie_name = strdup(args[1]);
1447 curproxy->cookie_len = strlen(curproxy->cookie_name);
1448
1449 cur_arg = 2;
1450 while (*(args[cur_arg])) {
1451 if (!strcmp(args[cur_arg], "rewrite")) {
1452 curproxy->options |= PR_O_COOK_RW;
1453 }
1454 else if (!strcmp(args[cur_arg], "indirect")) {
1455 curproxy->options |= PR_O_COOK_IND;
1456 }
1457 else if (!strcmp(args[cur_arg], "insert")) {
1458 curproxy->options |= PR_O_COOK_INS;
1459 }
1460 else if (!strcmp(args[cur_arg], "nocache")) {
1461 curproxy->options |= PR_O_COOK_NOC;
1462 }
1463 else if (!strcmp(args[cur_arg], "postonly")) {
1464 curproxy->options |= PR_O_COOK_POST;
1465 }
1466 else if (!strcmp(args[cur_arg], "prefix")) {
1467 curproxy->options |= PR_O_COOK_PFX;
1468 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001469 else if (!strcmp(args[cur_arg], "domain")) {
1470 if (!*args[cur_arg + 1]) {
1471 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1472 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001475 }
1476
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001477 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001478 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001479 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1480 " dots nor does not start with a dot."
1481 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001482 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001483 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001484 }
1485
1486 err = invalid_domainchar(args[cur_arg + 1]);
1487 if (err) {
1488 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1489 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001492 }
1493
Willy Tarreau68a897b2009-12-03 23:28:34 +01001494 if (!curproxy->cookie_domain) {
1495 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1496 } else {
1497 /* one domain was already specified, add another one by
1498 * building the string which will be returned along with
1499 * the cookie.
1500 */
1501 char *new_ptr;
1502 int new_len = strlen(curproxy->cookie_domain) +
1503 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1504 new_ptr = malloc(new_len);
1505 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1506 free(curproxy->cookie_domain);
1507 curproxy->cookie_domain = new_ptr;
1508 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001509 cur_arg++;
1510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001512 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001514 err_code |= ERR_ALERT | ERR_FATAL;
1515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516 }
1517 cur_arg++;
1518 }
1519 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1520 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1521 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001522 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 }
1524
1525 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1526 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001528 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 }
1530 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001531 else if (!strcmp(args[0], "persist")) { /* persist */
1532 if (*(args[1]) == 0) {
1533 Alert("parsing [%s:%d] : missing persist method.\n",
1534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001535 err_code |= ERR_ALERT | ERR_FATAL;
1536 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001537 }
1538
1539 if (!strncmp(args[1], "rdp-cookie", 10)) {
1540 curproxy->options2 |= PR_O2_RDPC_PRST;
1541
1542 if (*(args[1] + 10 ) == '(') { /* cookie name */
1543 const char *beg, *end;
1544
1545 beg = args[1] + 11;
1546 end = strchr(beg, ')');
1547
1548 if (!end || end == beg) {
1549 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1550 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001553 }
1554
1555 free(curproxy->rdp_cookie_name);
1556 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1557 curproxy->rdp_cookie_len = end-beg;
1558 }
1559 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1560 free(curproxy->rdp_cookie_name);
1561 curproxy->rdp_cookie_name = strdup("msts");
1562 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1563 }
1564 else { /* syntax */
1565 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1566 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001567 err_code |= ERR_ALERT | ERR_FATAL;
1568 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001569 }
1570 }
1571 else {
1572 Alert("parsing [%s:%d] : unknown persist method.\n",
1573 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001576 }
1577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001579 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580
Willy Tarreau977b8e42006-12-29 14:19:17 +01001581 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001582 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001583
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001585 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 }
1590 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001591 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 curproxy->appsession_name = strdup(args[1]);
1593 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1594 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001595 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1596 if (err) {
1597 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1598 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001601 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001602 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001603
Willy Tarreau51041c72007-09-09 21:56:53 +02001604 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1605 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001606 err_code |= ERR_ALERT | ERR_ABORT;
1607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001609
1610 cur_arg = 6;
1611 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001612 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1613 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001614 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001615 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001616 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001617 } else if (!strcmp(args[cur_arg], "prefix")) {
1618 curproxy->options2 |= PR_O2_AS_PFX;
1619 } else if (!strcmp(args[cur_arg], "mode")) {
1620 if (!*args[cur_arg + 1]) {
1621 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1622 file, linenum, args[0], args[cur_arg]);
1623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
1626
1627 cur_arg++;
1628 if (!strcmp(args[cur_arg], "query-string")) {
1629 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1630 curproxy->options2 |= PR_O2_AS_M_QS;
1631 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1632 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1633 curproxy->options2 |= PR_O2_AS_M_PP;
1634 } else {
1635 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
1638 }
1639 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001640 cur_arg++;
1641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 } /* Url App Session */
1643 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001644 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001646
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 if (*(args[4]) == 0) {
1649 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1650 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001654 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 curproxy->capture_name = strdup(args[2]);
1656 curproxy->capture_namelen = strlen(curproxy->capture_name);
1657 curproxy->capture_len = atol(args[4]);
1658 if (curproxy->capture_len >= CAPTURE_LEN) {
1659 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1660 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662 curproxy->capture_len = CAPTURE_LEN - 1;
1663 }
1664 curproxy->to_log |= LW_COOKIE;
1665 }
1666 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1667 struct cap_hdr *hdr;
1668
1669 if (curproxy == &defproxy) {
1670 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 +02001671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 }
1674
1675 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1676 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1677 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680 }
1681
1682 hdr = calloc(sizeof(struct cap_hdr), 1);
1683 hdr->next = curproxy->req_cap;
1684 hdr->name = strdup(args[3]);
1685 hdr->namelen = strlen(args[3]);
1686 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001687 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 hdr->index = curproxy->nb_req_cap++;
1689 curproxy->req_cap = hdr;
1690 curproxy->to_log |= LW_REQHDR;
1691 }
1692 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1693 struct cap_hdr *hdr;
1694
1695 if (curproxy == &defproxy) {
1696 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 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 }
1700
1701 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1702 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1703 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 }
1707 hdr = calloc(sizeof(struct cap_hdr), 1);
1708 hdr->next = curproxy->rsp_cap;
1709 hdr->name = strdup(args[3]);
1710 hdr->namelen = strlen(args[3]);
1711 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001712 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 hdr->index = curproxy->nb_rsp_cap++;
1714 curproxy->rsp_cap = hdr;
1715 curproxy->to_log |= LW_RSPHDR;
1716 }
1717 else {
1718 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1719 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 }
1723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 if (*(args[1]) == 0) {
1729 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1730 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 }
1734 curproxy->conn_retries = atol(args[1]);
1735 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001736 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1737 int pol = ACL_COND_NONE;
1738 struct acl_cond *cond;
1739
Willy Tarreaub099aca2008-10-12 17:26:37 +02001740 if (curproxy == &defproxy) {
1741 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001744 }
1745
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001746 if (!strcmp(args[1], "if"))
1747 pol = ACL_COND_IF;
1748 else if (!strcmp(args[1], "unless"))
1749 pol = ACL_COND_UNLESS;
1750
1751 if (pol == ACL_COND_NONE) {
1752 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1753 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001756 }
1757
1758 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1759 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1760 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001763 }
Willy Tarreau88922352009-10-04 22:02:50 +02001764 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001765 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001766 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001767 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001768 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001769 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001770 else if (!strcmp(args[0], "redirect")) {
1771 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001772 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001773 struct redirect_rule *rule;
1774 int cur_arg;
1775 int type = REDIRECT_TYPE_NONE;
1776 int code = 302;
1777 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001778 char *cookie = NULL;
1779 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001780 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001781
1782 cur_arg = 1;
1783 while (*(args[cur_arg])) {
1784 if (!strcmp(args[cur_arg], "location")) {
1785 if (!*args[cur_arg + 1]) {
1786 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1787 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001790 }
1791
1792 type = REDIRECT_TYPE_LOCATION;
1793 cur_arg++;
1794 destination = args[cur_arg];
1795 }
1796 else if (!strcmp(args[cur_arg], "prefix")) {
1797 if (!*args[cur_arg + 1]) {
1798 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1799 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001802 }
1803
1804 type = REDIRECT_TYPE_PREFIX;
1805 cur_arg++;
1806 destination = args[cur_arg];
1807 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001808 else if (!strcmp(args[cur_arg], "set-cookie")) {
1809 if (!*args[cur_arg + 1]) {
1810 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1811 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001814 }
1815
1816 cur_arg++;
1817 cookie = args[cur_arg];
1818 cookie_set = 1;
1819 }
1820 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1821 if (!*args[cur_arg + 1]) {
1822 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1823 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001826 }
1827
1828 cur_arg++;
1829 cookie = args[cur_arg];
1830 cookie_set = 0;
1831 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001832 else if (!strcmp(args[cur_arg],"code")) {
1833 if (!*args[cur_arg + 1]) {
1834 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1835 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001838 }
1839 cur_arg++;
1840 code = atol(args[cur_arg]);
1841 if (code < 301 || code > 303) {
1842 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1843 file, linenum, args[0], code);
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 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001848 else if (!strcmp(args[cur_arg],"drop-query")) {
1849 flags |= REDIRECT_FLAG_DROP_QS;
1850 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001851 else if (!strcmp(args[cur_arg], "if")) {
1852 pol = ACL_COND_IF;
1853 cur_arg++;
1854 break;
1855 }
1856 else if (!strcmp(args[cur_arg], "unless")) {
1857 pol = ACL_COND_UNLESS;
1858 cur_arg++;
1859 break;
1860 }
1861 else {
Willy Tarreau963abc32010-01-03 19:47:39 +01001862 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie' or 'drop-query' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001863 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001864 err_code |= ERR_ALERT | ERR_FATAL;
1865 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001866 }
1867 cur_arg++;
1868 }
1869
1870 if (type == REDIRECT_TYPE_NONE) {
1871 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1872 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001873 err_code |= ERR_ALERT | ERR_FATAL;
1874 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001875 }
1876
Willy Tarreauf285f542010-01-03 20:03:03 +01001877 if (pol != ACL_COND_NONE &&
1878 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001879 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001880 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001881 err_code |= ERR_ALERT | ERR_FATAL;
1882 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001883 }
1884
Willy Tarreauf285f542010-01-03 20:03:03 +01001885 if (cond) {
1886 cond->file = file;
1887 cond->line = linenum;
1888 curproxy->acl_requires |= cond->requires;
1889 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001890 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1891 rule->cond = cond;
1892 rule->rdr_str = strdup(destination);
1893 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001894 if (cookie) {
1895 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1896 * a clear consists in appending "; Max-Age=0" at the end.
1897 */
1898 rule->cookie_len = strlen(cookie);
1899 if (cookie_set)
1900 rule->cookie_str = strdup(cookie);
1901 else {
1902 rule->cookie_str = malloc(rule->cookie_len + 12);
1903 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1904 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1905 rule->cookie_len += 11;
1906 }
1907 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001908 rule->type = type;
1909 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001910 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001911 LIST_INIT(&rule->list);
1912 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001913 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001914 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001915 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001916 int pol = ACL_COND_NONE;
1917 struct acl_cond *cond;
1918 struct switching_rule *rule;
1919
Willy Tarreaub099aca2008-10-12 17:26:37 +02001920 if (curproxy == &defproxy) {
1921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001924 }
1925
Willy Tarreau55ea7572007-06-17 19:56:27 +02001926 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001927 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001928
1929 if (*(args[1]) == 0) {
1930 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001933 }
1934
1935 if (!strcmp(args[2], "if"))
1936 pol = ACL_COND_IF;
1937 else if (!strcmp(args[2], "unless"))
1938 pol = ACL_COND_UNLESS;
1939
1940 if (pol == ACL_COND_NONE) {
1941 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_ALERT | ERR_FATAL;
1944 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001945 }
1946
1947 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001948 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001949 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001952 }
1953
Willy Tarreau88922352009-10-04 22:02:50 +02001954 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001955 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001956 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001957 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001958 struct acl *acl;
1959 const char *name;
1960
1961 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1962 name = acl ? acl->name : "(unknown)";
1963 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1964 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001966 }
1967
Willy Tarreau55ea7572007-06-17 19:56:27 +02001968 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1969 rule->cond = cond;
1970 rule->be.name = strdup(args[1]);
1971 LIST_INIT(&rule->list);
1972 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001977
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1979 curproxy->uri_auth = NULL; /* we must detach from the default config */
1980
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01001981 if (!*args[1]) {
1982 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 } else if (!strcmp(args[1], "uri")) {
1984 if (*(args[2]) == 0) {
1985 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1989 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001990 err_code |= ERR_ALERT | ERR_ABORT;
1991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 }
1993 } else if (!strcmp(args[1], "realm")) {
1994 if (*(args[2]) == 0) {
1995 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001996 err_code |= ERR_ALERT | ERR_FATAL;
1997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1999 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_ABORT;
2001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002003 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002004 unsigned interval;
2005
2006 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2007 if (err) {
2008 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2009 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002012 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2013 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002014 err_code |= ERR_ALERT | ERR_ABORT;
2015 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 } else if (!strcmp(args[1], "auth")) {
2018 if (*(args[2]) == 0) {
2019 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2023 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_ALERT | ERR_ABORT;
2025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 }
2027 } else if (!strcmp(args[1], "scope")) {
2028 if (*(args[2]) == 0) {
2029 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002030 err_code |= ERR_ALERT | ERR_FATAL;
2031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2033 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_ABORT;
2035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 }
2037 } else if (!strcmp(args[1], "enable")) {
2038 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2039 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002040 err_code |= ERR_ALERT | ERR_ABORT;
2041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002043 } else if (!strcmp(args[1], "hide-version")) {
2044 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2045 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002046 err_code |= ERR_ALERT | ERR_ABORT;
2047 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002048 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002049 } else if (!strcmp(args[1], "show-legends")) {
2050 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2051 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2052 err_code |= ERR_ALERT | ERR_ABORT;
2053 goto out;
2054 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002055 } else if (!strcmp(args[1], "show-node")) {
2056
2057 if (*args[2]) {
2058 int i;
2059 char c;
2060
2061 for (i=0; args[2][i]; i++) {
2062 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002063 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002064 break;
2065 }
2066
2067 if (!i || args[2][i]) {
2068 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2069 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2070 file, linenum, args[0], args[1]);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074 }
2075
2076 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2077 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2078 err_code |= ERR_ALERT | ERR_ABORT;
2079 goto out;
2080 }
2081 } else if (!strcmp(args[1], "show-desc")) {
2082 char *desc = NULL;
2083
2084 if (*args[2]) {
2085 int i, len=0;
2086 char *d;
2087
2088 for(i=2; *args[i]; i++)
2089 len += strlen(args[i])+1;
2090
2091 desc = d = (char *)calloc(1, len);
2092
2093 d += sprintf(d, "%s", args[2]);
2094 for(i=3; *args[i]; i++)
2095 d += sprintf(d, " %s", args[i]);
2096 }
2097
2098 if (!*args[2] && !global.desc)
2099 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2100 file, linenum, args[1]);
2101 else {
2102 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2103 free(desc);
2104 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2105 err_code |= ERR_ALERT | ERR_ABORT;
2106 goto out;
2107 }
2108 free(desc);
2109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002111stats_error_parsing:
2112 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2113 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_ALERT | ERR_FATAL;
2115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 }
2117 }
2118 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002119 int optnum;
2120
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002121 if (*(args[1]) == '\0') {
2122 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002124 err_code |= ERR_ALERT | ERR_FATAL;
2125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002127
2128 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2129 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002130 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2131 err_code |= ERR_WARN;
2132 goto out;
2133 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002134
Willy Tarreau3842f002009-06-14 11:39:52 +02002135 curproxy->no_options &= ~cfg_opts[optnum].val;
2136 curproxy->options &= ~cfg_opts[optnum].val;
2137
2138 switch (kwm) {
2139 case KWM_STD:
2140 curproxy->options |= cfg_opts[optnum].val;
2141 break;
2142 case KWM_NO:
2143 curproxy->no_options |= cfg_opts[optnum].val;
2144 break;
2145 case KWM_DEF: /* already cleared */
2146 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002147 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002148
Willy Tarreau93893792009-07-23 13:19:11 +02002149 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002150 }
2151 }
2152
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002153 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2154 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002155 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2156 err_code |= ERR_WARN;
2157 goto out;
2158 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002159
Willy Tarreau3842f002009-06-14 11:39:52 +02002160 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2161 curproxy->options2 &= ~cfg_opts2[optnum].val;
2162
2163 switch (kwm) {
2164 case KWM_STD:
2165 curproxy->options2 |= cfg_opts2[optnum].val;
2166 break;
2167 case KWM_NO:
2168 curproxy->no_options2 |= cfg_opts2[optnum].val;
2169 break;
2170 case KWM_DEF: /* already cleared */
2171 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002172 }
Willy Tarreau93893792009-07-23 13:19:11 +02002173 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002174 }
2175 }
2176
Willy Tarreau3842f002009-06-14 11:39:52 +02002177 if (kwm != KWM_STD) {
2178 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002179 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002182 }
2183
Emeric Brun3a058f32009-06-30 18:26:00 +02002184 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002186 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002188 if (*(args[2]) != '\0') {
2189 if (!strcmp(args[2], "clf")) {
2190 curproxy->options2 |= PR_O2_CLFLOG;
2191 } else {
2192 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002195 }
2196 }
2197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 else if (!strcmp(args[1], "tcplog"))
2199 /* generate a detailed TCP log */
2200 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 else if (!strcmp(args[1], "tcpka")) {
2202 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002203 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002205
2206 if (curproxy->cap & PR_CAP_FE)
2207 curproxy->options |= PR_O_TCP_CLI_KA;
2208 if (curproxy->cap & PR_CAP_BE)
2209 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 }
2211 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_WARN;
2214
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002216 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002217 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002218 curproxy->options &= ~PR_O_SMTP_CHK;
2219 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 if (!*args[2]) { /* no argument */
2221 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2222 curproxy->check_len = strlen(DEF_CHECK_REQ);
2223 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002224 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 curproxy->check_req = (char *)malloc(reqlen);
2226 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2227 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2228 } else { /* more arguments : METHOD URI [HTTP_VER] */
2229 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2230 if (*args[4])
2231 reqlen += strlen(args[4]);
2232 else
2233 reqlen += strlen("HTTP/1.0");
2234
2235 curproxy->check_req = (char *)malloc(reqlen);
2236 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2237 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2238 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002239 }
2240 else if (!strcmp(args[1], "ssl-hello-chk")) {
2241 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002242 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002244
Willy Tarreaua534fea2008-08-03 12:19:50 +02002245 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002246 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002247 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002248 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
Willy Tarreau23677902007-05-08 23:50:35 +02002250 else if (!strcmp(args[1], "smtpchk")) {
2251 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002252 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002253 curproxy->options &= ~PR_O_HTTP_CHK;
2254 curproxy->options &= ~PR_O_SSL3_CHK;
2255 curproxy->options |= PR_O_SMTP_CHK;
2256
2257 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2258 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2259 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2260 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2261 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2262 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2263 curproxy->check_req = (char *)malloc(reqlen);
2264 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2265 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2266 } else {
2267 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2268 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2269 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2270 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2271 }
2272 }
2273 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002274 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002275 int cur_arg;
2276
2277 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2278 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002279 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002280
2281 curproxy->options |= PR_O_FWDFOR;
2282
2283 free(curproxy->fwdfor_hdr_name);
2284 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2285 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2286
2287 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2288 cur_arg = 2;
2289 while (*(args[cur_arg])) {
2290 if (!strcmp(args[cur_arg], "except")) {
2291 /* suboption except - needs additional argument for it */
2292 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2293 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2294 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002297 }
2298 /* flush useless bits */
2299 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002300 cur_arg += 2;
2301 } else if (!strcmp(args[cur_arg], "header")) {
2302 /* suboption header - needs additional argument for it */
2303 if (*(args[cur_arg+1]) == 0) {
2304 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2305 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002308 }
2309 free(curproxy->fwdfor_hdr_name);
2310 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2311 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2312 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002313 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002314 /* unknown suboption - catchall */
2315 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2316 file, linenum, args[0], args[1]);
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 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002320 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002321 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002322 else if (!strcmp(args[1], "originalto")) {
2323 int cur_arg;
2324
2325 /* insert x-original-to field, but not for the IP address listed as an except.
2326 * set default options (ie: bitfield, header name, etc)
2327 */
2328
2329 curproxy->options |= PR_O_ORGTO;
2330
2331 free(curproxy->orgto_hdr_name);
2332 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2333 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2334
2335 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2336 cur_arg = 2;
2337 while (*(args[cur_arg])) {
2338 if (!strcmp(args[cur_arg], "except")) {
2339 /* suboption except - needs additional argument for it */
2340 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2341 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2342 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002345 }
2346 /* flush useless bits */
2347 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2348 cur_arg += 2;
2349 } else if (!strcmp(args[cur_arg], "header")) {
2350 /* suboption header - needs additional argument for it */
2351 if (*(args[cur_arg+1]) == 0) {
2352 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2353 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002356 }
2357 free(curproxy->orgto_hdr_name);
2358 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2359 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2360 cur_arg += 2;
2361 } else {
2362 /* unknown suboption - catchall */
2363 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2364 file, linenum, args[0], args[1]);
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 } /* end while loop */
2369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 else {
2371 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 }
Willy Tarreau93893792009-07-23 13:19:11 +02002375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002377 else if (!strcmp(args[0], "default_backend")) {
2378 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002380
2381 if (*(args[1]) == 0) {
2382 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002385 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002387 curproxy->defbe.name = strdup(args[1]);
2388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002392
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002393 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2394 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 /* enable reconnections to dispatch */
2397 curproxy->options |= PR_O_REDISP;
2398 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002399 else if (!strcmp(args[0], "http-check")) {
2400 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002402
2403 if (strcmp(args[1], "disable-on-404") == 0) {
2404 /* enable a graceful server shutdown on an HTTP 404 response */
2405 curproxy->options |= PR_O_DISABLE404;
2406 }
2407 else {
2408 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002411 }
2412 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002413 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002414 if (curproxy == &defproxy) {
2415 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002418 }
2419
Willy Tarreaub80c2302007-11-30 20:51:32 +01002420 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002421 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002422
2423 if (strcmp(args[1], "fail") == 0) {
2424 /* add a condition to fail monitor requests */
2425 int pol = ACL_COND_NONE;
2426 struct acl_cond *cond;
2427
2428 if (!strcmp(args[2], "if"))
2429 pol = ACL_COND_IF;
2430 else if (!strcmp(args[2], "unless"))
2431 pol = ACL_COND_UNLESS;
2432
2433 if (pol == ACL_COND_NONE) {
2434 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2435 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002438 }
2439
2440 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2441 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2442 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002445 }
Willy Tarreau88922352009-10-04 22:02:50 +02002446 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002447 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002448 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002449 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2450 }
2451 else {
2452 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002455 }
2456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457#ifdef TPROXY
2458 else if (!strcmp(args[0], "transparent")) {
2459 /* enable transparent proxy connections */
2460 curproxy->options |= PR_O_TRANSP;
2461 }
2462#endif
2463 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002464 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002466
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 if (*(args[1]) == 0) {
2468 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 }
2472 curproxy->maxconn = atol(args[1]);
2473 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002474 else if (!strcmp(args[0], "backlog")) { /* backlog */
2475 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002477
2478 if (*(args[1]) == 0) {
2479 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002482 }
2483 curproxy->backlog = atol(args[1]);
2484 }
Willy Tarreau86034312006-12-29 00:10:33 +01002485 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002486 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488
Willy Tarreau86034312006-12-29 00:10:33 +01002489 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 Tarreau86034312006-12-29 00:10:33 +01002493 }
2494 curproxy->fullconn = atol(args[1]);
2495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2497 if (*(args[1]) == 0) {
2498 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002502 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2503 if (err) {
2504 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2505 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002508 }
2509 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 }
2511 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2512 if (curproxy == &defproxy) {
2513 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002517 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002518 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002519
Willy Tarreaubaaee002006-06-26 02:48:02 +02002520 if (strchr(args[1], ':') == NULL) {
2521 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 }
2525 curproxy->dispatch_addr = *str2sa(args[1]);
2526 }
2527 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002528 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002531 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002532 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2533 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002538 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2539 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2540 err_code |= ERR_WARN;
2541
2542 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2543 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2544 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2545 }
2546 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2547 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2548 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2549 }
2550 else {
2551 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
2554 }
2555 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002556 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002558 char *rport, *raddr;
2559 short realport = 0;
2560 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002562 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002567 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569
2570 if (!*args[2]) {
2571 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2572 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002576
2577 err = invalid_char(args[1]);
2578 if (err) {
2579 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2580 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002583 }
2584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2586 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_ABORT;
2588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
2590
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002591 if (!defsrv) {
2592 /* the servers are linked backwards first */
2593 newsrv->next = curproxy->srv;
2594 curproxy->srv = newsrv;
2595 newsrv->proxy = curproxy;
2596 newsrv->conf.file = file;
2597 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002599 LIST_INIT(&newsrv->pendconns);
2600 do_check = 0;
2601 newsrv->state = SRV_RUNNING; /* early server setup */
2602 newsrv->last_change = now.tv_sec;
2603 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002605 /* several ways to check the port component :
2606 * - IP => port=+0, relative
2607 * - IP: => port=+0, relative
2608 * - IP:N => port=N, absolute
2609 * - IP:+N => port=+N, relative
2610 * - IP:-N => port=-N, relative
2611 */
2612 raddr = strdup(args[2]);
2613 rport = strchr(raddr, ':');
2614 if (rport) {
2615 *rport++ = 0;
2616 realport = atol(rport);
2617 if (!isdigit((unsigned char)*rport))
2618 newsrv->state |= SRV_MAPPORTS;
2619 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002621
2622 newsrv->addr = *str2sa(raddr);
2623 newsrv->addr.sin_port = htons(realport);
2624 free(raddr);
2625
2626 newsrv->check_port = curproxy->defsrv.check_port;
2627 newsrv->inter = curproxy->defsrv.inter;
2628 newsrv->fastinter = curproxy->defsrv.fastinter;
2629 newsrv->downinter = curproxy->defsrv.downinter;
2630 newsrv->rise = curproxy->defsrv.rise;
2631 newsrv->fall = curproxy->defsrv.fall;
2632 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2633 newsrv->minconn = curproxy->defsrv.minconn;
2634 newsrv->maxconn = curproxy->defsrv.maxconn;
2635 newsrv->slowstart = curproxy->defsrv.slowstart;
2636 newsrv->onerror = curproxy->defsrv.onerror;
2637 newsrv->consecutive_errors_limit
2638 = curproxy->defsrv.consecutive_errors_limit;
2639 newsrv->uweight = newsrv->iweight
2640 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002642 newsrv->curfd = -1; /* no health-check in progress */
2643 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002645 cur_arg = 3;
2646 } else {
2647 newsrv = &curproxy->defsrv;
2648 cur_arg = 1;
2649 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002650
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002652 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002653 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002654
2655 if (!*args[cur_arg + 1]) {
2656 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2657 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002660 }
2661
2662 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002663 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002664
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002665 if (newsrv->puid <= 0) {
2666 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002667 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002670 }
2671
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002672 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2673 if (node) {
2674 struct server *target = container_of(node, struct server, conf.id);
2675 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2676 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002681 cur_arg += 2;
2682 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002683 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 newsrv->cookie = strdup(args[cur_arg + 1]);
2685 newsrv->cklen = strlen(args[cur_arg + 1]);
2686 cur_arg += 2;
2687 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002688 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01002689 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2690 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2691 cur_arg += 2;
2692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002694 if (!*args[cur_arg + 1]) {
2695 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2696 file, linenum, args[cur_arg]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002702 if (newsrv->rise <= 0) {
2703 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2704 file, linenum, args[cur_arg]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 newsrv->health = newsrv->rise;
2710 cur_arg += 2;
2711 }
2712 else if (!strcmp(args[cur_arg], "fall")) {
2713 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002714
2715 if (!*args[cur_arg + 1]) {
2716 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2717 file, linenum, args[cur_arg]);
2718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
2720 }
2721
2722 if (newsrv->fall <= 0) {
2723 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2724 file, linenum, args[cur_arg]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 cur_arg += 2;
2730 }
2731 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002732 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2733 if (err) {
2734 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2735 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002738 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002739 if (val <= 0) {
2740 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2741 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002744 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002745 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 cur_arg += 2;
2747 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002748 else if (!strcmp(args[cur_arg], "fastinter")) {
2749 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2750 if (err) {
2751 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2752 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002755 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002756 if (val <= 0) {
2757 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2758 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002761 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002762 newsrv->fastinter = val;
2763 cur_arg += 2;
2764 }
2765 else if (!strcmp(args[cur_arg], "downinter")) {
2766 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2767 if (err) {
2768 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2769 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002772 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002773 if (val <= 0) {
2774 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2775 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002778 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002779 newsrv->downinter = val;
2780 cur_arg += 2;
2781 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002782 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002783 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002784 cur_arg += 2;
2785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 else if (!strcmp(args[cur_arg], "port")) {
2787 newsrv->check_port = atol(args[cur_arg + 1]);
2788 cur_arg += 2;
2789 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002790 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 newsrv->state |= SRV_BACKUP;
2792 cur_arg ++;
2793 }
2794 else if (!strcmp(args[cur_arg], "weight")) {
2795 int w;
2796 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002797 if (w < 0 || w > 256) {
2798 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002803 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 cur_arg += 2;
2805 }
2806 else if (!strcmp(args[cur_arg], "minconn")) {
2807 newsrv->minconn = atol(args[cur_arg + 1]);
2808 cur_arg += 2;
2809 }
2810 else if (!strcmp(args[cur_arg], "maxconn")) {
2811 newsrv->maxconn = atol(args[cur_arg + 1]);
2812 cur_arg += 2;
2813 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002814 else if (!strcmp(args[cur_arg], "maxqueue")) {
2815 newsrv->maxqueue = atol(args[cur_arg + 1]);
2816 cur_arg += 2;
2817 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002818 else if (!strcmp(args[cur_arg], "slowstart")) {
2819 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002820 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002821 if (err) {
2822 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2823 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002826 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002827 if (val <= 0) {
2828 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2829 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002832 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002833 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002834 cur_arg += 2;
2835 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002836 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002837
2838 if (!*args[cur_arg + 1]) {
2839 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2840 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002843 }
2844
2845 newsrv->trackit = strdup(args[cur_arg + 1]);
2846
2847 cur_arg += 2;
2848 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002849 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 global.maxsock++;
2851 do_check = 1;
2852 cur_arg += 1;
2853 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002854 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002855 if (!strcmp(args[cur_arg + 1], "none"))
2856 newsrv->observe = HANA_OBS_NONE;
2857 else if (!strcmp(args[cur_arg + 1], "layer4"))
2858 newsrv->observe = HANA_OBS_LAYER4;
2859 else if (!strcmp(args[cur_arg + 1], "layer7")) {
2860 if (curproxy->mode != PR_MODE_HTTP) {
2861 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
2862 file, linenum, args[cur_arg + 1]);
2863 err_code |= ERR_ALERT;
2864 }
2865 newsrv->observe = HANA_OBS_LAYER7;
2866 }
2867 else {
2868 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
2869 "'l4events', 'http-responses' but get '%s'\n",
2870 file, linenum, args[cur_arg], args[cur_arg + 1]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
2875 cur_arg += 2;
2876 }
2877 else if (!strcmp(args[cur_arg], "on-error")) {
2878 if (!strcmp(args[cur_arg + 1], "fastinter"))
2879 newsrv->onerror = HANA_ONERR_FASTINTER;
2880 else if (!strcmp(args[cur_arg + 1], "fail-check"))
2881 newsrv->onerror = HANA_ONERR_FAILCHK;
2882 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
2883 newsrv->onerror = HANA_ONERR_SUDDTH;
2884 else if (!strcmp(args[cur_arg + 1], "mark-down"))
2885 newsrv->onerror = HANA_ONERR_MARKDWN;
2886 else {
2887 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
2888 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
2889 file, linenum, args[cur_arg], args[cur_arg + 1]);
2890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
2894 cur_arg += 2;
2895 }
2896 else if (!strcmp(args[cur_arg], "error-limit")) {
2897 if (!*args[cur_arg + 1]) {
2898 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2899 file, linenum, args[cur_arg]);
2900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902 }
2903
2904 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
2905
2906 if (newsrv->consecutive_errors_limit <= 0) {
2907 Alert("parsing [%s:%d]: %s has to be > 0.\n",
2908 file, linenum, args[cur_arg]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002913 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002914 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002916#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002917 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002918 file, linenum, "source", "usesrc");
2919#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002920 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002922#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
2926 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002927 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2928
2929 if (port_low != port_high) {
2930 int i;
2931 if (port_low <= 0 || port_low > 65535 ||
2932 port_high <= 0 || port_high > 65535 ||
2933 port_low > port_high) {
2934 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2935 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002938 }
2939 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2940 for (i = 0; i < newsrv->sport_range->size; i++)
2941 newsrv->sport_range->ports[i] = port_low + i;
2942 }
2943
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002945 while (*(args[cur_arg])) {
2946 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002947#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2948#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002949 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2950 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2951 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002954 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002955#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002956 if (!*args[cur_arg + 1]) {
2957 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2958 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002961 }
2962 if (!strcmp(args[cur_arg + 1], "client")) {
2963 newsrv->state |= SRV_TPROXY_CLI;
2964 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2965 newsrv->state |= SRV_TPROXY_CIP;
2966 } else {
2967 newsrv->state |= SRV_TPROXY_ADDR;
2968 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2969 }
2970 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002971#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002972 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002973#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002974 cur_arg += 2;
2975 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002976#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002977 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002978 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002981#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2982 } /* "usesrc" */
2983
2984 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2985#ifdef SO_BINDTODEVICE
2986 if (!*args[cur_arg + 1]) {
2987 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2988 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002991 }
2992 if (newsrv->iface_name)
2993 free(newsrv->iface_name);
2994
2995 newsrv->iface_name = strdup(args[cur_arg + 1]);
2996 newsrv->iface_len = strlen(newsrv->iface_name);
2997 global.last_checks |= LSTCHK_NETADM;
2998#else
2999 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3000 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003003#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003004 cur_arg += 2;
3005 continue;
3006 }
3007 /* this keyword in not an option of "source" */
3008 break;
3009 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003011 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003012 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3013 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003018 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003019 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 +01003020 file, linenum, newsrv->id);
3021 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003022 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 +01003023 file, linenum);
3024
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 }
3028 }
3029
3030 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003031 if (newsrv->trackit) {
3032 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3033 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003036 }
3037
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003038 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3039 newsrv->check_port = newsrv->check_addr.sin_port;
3040
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3042 newsrv->check_port = realport; /* by default */
3043 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003044 /* not yet valid, because no port was set on
3045 * the server either. We'll check if we have
3046 * a known port on the first listener.
3047 */
3048 struct listener *l;
3049 l = curproxy->listen;
3050 if (l) {
3051 int port;
3052 port = (l->addr.ss_family == AF_INET6)
3053 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3054 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3055 newsrv->check_port = port;
3056 }
3057 }
3058 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3060 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003064
3065 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 newsrv->state |= SRV_CHECKED;
3067 }
3068
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003069 if (!defsrv) {
3070 if (newsrv->state & SRV_BACKUP)
3071 curproxy->srv_bck++;
3072 else
3073 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003074
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003075 newsrv->prev_state = newsrv->state;
3076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 }
3078 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003079 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 int facility;
3081
3082 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3083 curproxy->logfac1 = global.logfac1;
3084 curproxy->logsrv1 = global.logsrv1;
3085 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003086 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 curproxy->logfac2 = global.logfac2;
3088 curproxy->logsrv2 = global.logsrv2;
3089 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003090 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 }
3092 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003093 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094
3095 facility = get_log_facility(args[2]);
3096 if (facility < 0) {
3097 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3098 exit(1);
3099 }
3100
3101 level = 7; /* max syslog level = debug */
3102 if (*(args[3])) {
3103 level = get_log_level(args[3]);
3104 if (level < 0) {
3105 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3106 exit(1);
3107 }
3108 }
3109
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003110 minlvl = 0; /* limit syslog level to this level (emerg) */
3111 if (*(args[4])) {
3112 minlvl = get_log_level(args[4]);
3113 if (level < 0) {
3114 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3115 exit(1);
3116 }
3117 }
3118
Robert Tsai81ae1952007-12-05 10:47:29 +01003119 if (args[1][0] == '/') {
3120 logsrv.u.addr.sa_family = AF_UNIX;
3121 logsrv.u.un = *str2sun(args[1]);
3122 } else {
3123 logsrv.u.addr.sa_family = AF_INET;
3124 logsrv.u.in = *str2sa(args[1]);
3125 if (!logsrv.u.in.sin_port) {
3126 logsrv.u.in.sin_port =
3127 htons(SYSLOG_PORT);
3128 }
3129 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130
3131 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003132 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 curproxy->logfac1 = facility;
3134 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003135 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 }
3137 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003138 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 curproxy->logfac2 = facility;
3140 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003141 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 }
3143 else {
3144 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148 }
3149 else {
3150 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3151 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
3155 }
3156 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003157 int cur_arg;
3158
Willy Tarreau977b8e42006-12-29 14:19:17 +01003159 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003161
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003163 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3164 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003168
3169 /* we must first clear any optional default setting */
3170 curproxy->options &= ~PR_O_TPXY_MASK;
3171 free(curproxy->iface_name);
3172 curproxy->iface_name = NULL;
3173 curproxy->iface_len = 0;
3174
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 curproxy->source_addr = *str2sa(args[1]);
3176 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003177
3178 cur_arg = 2;
3179 while (*(args[cur_arg])) {
3180 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003181#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3182#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003183 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3184 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3185 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003188 }
3189#endif
3190 if (!*args[cur_arg + 1]) {
3191 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3192 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003195 }
3196
3197 if (!strcmp(args[cur_arg + 1], "client")) {
3198 curproxy->options |= PR_O_TPXY_CLI;
3199 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3200 curproxy->options |= PR_O_TPXY_CIP;
3201 } else {
3202 curproxy->options |= PR_O_TPXY_ADDR;
3203 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3204 }
3205 global.last_checks |= LSTCHK_NETADM;
3206#if !defined(CONFIG_HAP_LINUX_TPROXY)
3207 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003208#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003209#else /* no TPROXY support */
3210 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003211 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003214#endif
3215 cur_arg += 2;
3216 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003217 }
3218
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003219 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3220#ifdef SO_BINDTODEVICE
3221 if (!*args[cur_arg + 1]) {
3222 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3223 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003226 }
3227 if (curproxy->iface_name)
3228 free(curproxy->iface_name);
3229
3230 curproxy->iface_name = strdup(args[cur_arg + 1]);
3231 curproxy->iface_len = strlen(curproxy->iface_name);
3232 global.last_checks |= LSTCHK_NETADM;
3233#else
3234 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3235 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003238#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003239 cur_arg += 2;
3240 continue;
3241 }
3242 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3243 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003248 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3249 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3250 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3255 regex_t *preg;
3256 if (curproxy == &defproxy) {
3257 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003261 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003263
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 if (*(args[1]) == 0 || *(args[2]) == 0) {
3265 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3266 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
3270
3271 preg = calloc(1, sizeof(regex_t));
3272 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3273 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277
3278 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3279 if (err) {
3280 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3281 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003284 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 }
3286 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3287 regex_t *preg;
3288 if (curproxy == &defproxy) {
3289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003293 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003295
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if (*(args[1]) == 0) {
3297 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301
3302 preg = calloc(1, sizeof(regex_t));
3303 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3304 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
3308
3309 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003310 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
3312 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3313 regex_t *preg;
3314 if (curproxy == &defproxy) {
3315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003319 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003321
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 if (*(args[1]) == 0) {
3323 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
3327
3328 preg = calloc(1, sizeof(regex_t));
3329 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3330 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
3334
3335 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003336 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
3338 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3339 regex_t *preg;
3340 if (curproxy == &defproxy) {
3341 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003345 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003347
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 if (*(args[1]) == 0) {
3349 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
3353
3354 preg = calloc(1, sizeof(regex_t));
3355 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3356 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
3360
3361 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003362 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
3364 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3365 regex_t *preg;
3366 if (curproxy == &defproxy) {
3367 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003371 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003373
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 if (*(args[1]) == 0) {
3375 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
3379
3380 preg = calloc(1, sizeof(regex_t));
3381 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3382 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
3386
3387 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003388 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003390 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3391 regex_t *preg;
3392 if (curproxy == &defproxy) {
3393 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003396 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003397 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003399
Willy Tarreaub8750a82006-09-03 09:56:00 +02003400 if (*(args[1]) == 0) {
3401 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003404 }
3405
3406 preg = calloc(1, sizeof(regex_t));
3407 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3408 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003411 }
3412
3413 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003414 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003415 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003416 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3417 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003418 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003422 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003423 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003424 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003425
Willy Tarreau977b8e42006-12-29 14:19:17 +01003426 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003427 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003431 }
3432
3433 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003434 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003435 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003438 }
3439
3440 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003441 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003442 }
3443 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3444 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003445 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003446 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003449 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003450 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003452
Willy Tarreau977b8e42006-12-29 14:19:17 +01003453 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003454 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003458 }
3459
3460 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003461 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003462 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003465 }
3466
3467 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003468 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3471 regex_t *preg;
3472 if (curproxy == &defproxy) {
3473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003477 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003479
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 if (*(args[1]) == 0 || *(args[2]) == 0) {
3481 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003485 }
3486
3487 preg = calloc(1, sizeof(regex_t));
3488 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3489 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 }
3493
3494 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3495 if (err) {
3496 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3497 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003501 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 }
3503 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3504 regex_t *preg;
3505 if (curproxy == &defproxy) {
3506 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003510 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003512
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 if (*(args[1]) == 0) {
3514 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 }
3518
3519 preg = calloc(1, sizeof(regex_t));
3520 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3521 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
3525
3526 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003527 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
3529 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3530 regex_t *preg;
3531 if (curproxy == &defproxy) {
3532 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003536 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003538
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 if (*(args[1]) == 0) {
3540 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
3544
3545 preg = calloc(1, sizeof(regex_t));
3546 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3547 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 }
3551
3552 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003553 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
3555 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3556 regex_t *preg;
3557 if (curproxy == &defproxy) {
3558 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003562 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003564
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 if (*(args[1]) == 0) {
3566 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 }
3570
3571 preg = calloc(1, sizeof(regex_t));
3572 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3573 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 }
3577
3578 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003579 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
3581 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3582 regex_t *preg;
3583 if (curproxy == &defproxy) {
3584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003588 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003590
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 if (*(args[1]) == 0) {
3592 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 }
3596
3597 preg = calloc(1, sizeof(regex_t));
3598 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3599 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 }
3603
3604 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003605 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003607 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3608 regex_t *preg;
3609 if (curproxy == &defproxy) {
3610 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003613 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003614 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003616
Willy Tarreaub8750a82006-09-03 09:56:00 +02003617 if (*(args[1]) == 0) {
3618 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003621 }
3622
3623 preg = calloc(1, sizeof(regex_t));
3624 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3625 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003626 err_code |= ERR_ALERT | ERR_FATAL;
3627 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003628 }
3629
3630 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003631 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003634 struct wordlist *wl;
3635
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 if (curproxy == &defproxy) {
3637 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003641 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 if (*(args[1]) == 0) {
3645 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003648 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003649
3650 wl = calloc(1, sizeof(*wl));
3651 wl->s = strdup(args[1]);
3652 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003653 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 }
3655 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3656 regex_t *preg;
3657
3658 if (*(args[1]) == 0 || *(args[2]) == 0) {
3659 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3660 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003664 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003666
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 preg = calloc(1, sizeof(regex_t));
3668 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3669 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 }
3673
3674 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3675 if (err) {
3676 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3677 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003680 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003681 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
3683 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3684 regex_t *preg;
3685 if (curproxy == &defproxy) {
3686 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003690 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003691 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003692
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 if (*(args[1]) == 0) {
3694 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 }
3698
3699 preg = calloc(1, sizeof(regex_t));
3700 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3701 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
3705
3706 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3707 if (err) {
3708 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3709 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 }
3713 }
3714 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3715 regex_t *preg;
3716 if (curproxy == &defproxy) {
3717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003721 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003723
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 if (*(args[1]) == 0) {
3725 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
3729
3730 preg = calloc(1, sizeof(regex_t));
3731 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3732 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 }
3736
3737 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3738 if (err) {
3739 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3740 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 }
3744 }
3745 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3746 regex_t *preg;
3747 if (curproxy == &defproxy) {
3748 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754
3755 if (*(args[1]) == 0 || *(args[2]) == 0) {
3756 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3757 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 }
3761
3762 preg = calloc(1, sizeof(regex_t));
3763 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3764 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
3768
3769 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3770 if (err) {
3771 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3772 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 }
3776 }
3777 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3778 regex_t *preg;
3779 if (curproxy == &defproxy) {
3780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003784 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003786
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 if (*(args[1]) == 0) {
3788 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 }
3792
3793 preg = calloc(1, sizeof(regex_t));
3794 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3795 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 }
3799
3800 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3801 if (err) {
3802 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3803 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 }
3807 }
3808 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3809 regex_t *preg;
3810 if (curproxy == &defproxy) {
3811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003815 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003817
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 if (*(args[1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
3823
3824 preg = calloc(1, sizeof(regex_t));
3825 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3826 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 }
3830
3831 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3832 if (err) {
3833 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3834 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 }
3838 }
3839 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003840 struct wordlist *wl;
3841
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 if (curproxy == &defproxy) {
3843 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003847 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 if (*(args[1]) == 0) {
3851 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 }
3855
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003856 wl = calloc(1, sizeof(*wl));
3857 wl->s = strdup(args[1]);
3858 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
3860 else if (!strcmp(args[0], "errorloc") ||
3861 !strcmp(args[0], "errorloc302") ||
3862 !strcmp(args[0], "errorloc303")) { /* error location */
3863 int errnum, errlen;
3864 char *err;
3865
Willy Tarreau977b8e42006-12-29 14:19:17 +01003866 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003868
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003870 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
3874
3875 errnum = atol(args[1]);
3876 if (!strcmp(args[0], "errorloc303")) {
3877 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3878 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3879 } else {
3880 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3881 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3882 }
3883
Willy Tarreau0f772532006-12-23 20:51:41 +01003884 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3885 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003886 chunk_destroy(&curproxy->errmsg[rc]);
3887 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003888 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003891
3892 if (rc >= HTTP_ERR_SIZE) {
3893 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3894 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895 free(err);
3896 }
3897 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003898 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3899 int errnum, errlen, fd;
3900 char *err;
3901 struct stat stat;
3902
3903 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003905
3906 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003907 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003910 }
3911
3912 fd = open(args[2], O_RDONLY);
3913 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3914 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3915 file, linenum, args[2], args[1]);
3916 if (fd >= 0)
3917 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003920 }
3921
Willy Tarreau27a674e2009-08-17 07:23:33 +02003922 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003923 errlen = stat.st_size;
3924 } else {
3925 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003926 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003928 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003929 }
3930
3931 err = malloc(errlen); /* malloc() must succeed during parsing */
3932 errnum = read(fd, err, errlen);
3933 if (errnum != errlen) {
3934 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3935 file, linenum, args[2], args[1]);
3936 close(fd);
3937 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003940 }
3941 close(fd);
3942
3943 errnum = atol(args[1]);
3944 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3945 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003946 chunk_destroy(&curproxy->errmsg[rc]);
3947 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003948 break;
3949 }
3950 }
3951
3952 if (rc >= HTTP_ERR_SIZE) {
3953 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3954 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003956 free(err);
3957 }
3958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003960 struct cfg_kw_list *kwl;
3961 int index;
3962
3963 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3964 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3965 if (kwl->kw[index].section != CFG_LISTEN)
3966 continue;
3967 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3968 /* prepare error message just in case */
3969 snprintf(trash, sizeof(trash),
3970 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003971 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3972 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003973 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003976 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003977 else if (rc > 0) {
3978 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_WARN;
3980 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003981 }
Willy Tarreau93893792009-07-23 13:19:11 +02003982 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003983 }
3984 }
3985 }
3986
Willy Tarreau6daf3432008-01-22 16:44:08 +01003987 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 }
Willy Tarreau93893792009-07-23 13:19:11 +02003991 out:
3992 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993}
3994
3995
3996/*
3997 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003998 * Returns the error code, 0 if OK, or any combination of :
3999 * - ERR_ABORT: must abort ASAP
4000 * - ERR_FATAL: we can continue parsing but not start the service
4001 * - ERR_WARN: a warning has been emitted
4002 * - ERR_ALERT: an alert has been emitted
4003 * Only the two first ones can stop processing, the two others are just
4004 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004006int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004008 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 FILE *f;
4010 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004012 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 if ((f=fopen(file,"r")) == NULL)
4015 return -1;
4016
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004017 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004018 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004019 char *end;
4020 char *args[MAX_LINE_ARGS + 1];
4021 char *line = thisline;
4022
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 linenum++;
4024
4025 end = line + strlen(line);
4026
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004027 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4028 /* Check if we reached the limit and the last char is not \n.
4029 * Watch out for the last line without the terminating '\n'!
4030 */
4031 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004032 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004033 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004034 }
4035
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004037 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 line++;
4039
4040 arg = 0;
4041 args[arg] = line;
4042
4043 while (*line && arg < MAX_LINE_ARGS) {
4044 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4045 * C equivalent value. Other combinations left unchanged (eg: \1).
4046 */
4047 if (*line == '\\') {
4048 int skip = 0;
4049 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4050 *line = line[1];
4051 skip = 1;
4052 }
4053 else if (line[1] == 'r') {
4054 *line = '\r';
4055 skip = 1;
4056 }
4057 else if (line[1] == 'n') {
4058 *line = '\n';
4059 skip = 1;
4060 }
4061 else if (line[1] == 't') {
4062 *line = '\t';
4063 skip = 1;
4064 }
4065 else if (line[1] == 'x') {
4066 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
4067 unsigned char hex1, hex2;
4068 hex1 = toupper(line[2]) - '0';
4069 hex2 = toupper(line[3]) - '0';
4070 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4071 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4072 *line = (hex1<<4) + hex2;
4073 skip = 3;
4074 }
4075 else {
4076 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004077 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 }
4079 }
4080 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004081 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 end -= skip;
4083 }
4084 line++;
4085 }
4086 else if (*line == '#' || *line == '\n' || *line == '\r') {
4087 /* end of string, end of loop */
4088 *line = 0;
4089 break;
4090 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004091 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004093 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004094 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004095 line++;
4096 args[++arg] = line;
4097 }
4098 else {
4099 line++;
4100 }
4101 }
4102
4103 /* empty line */
4104 if (!**args)
4105 continue;
4106
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004107 if (*line) {
4108 /* we had to stop due to too many args.
4109 * Let's terminate the string, print the offending part then cut the
4110 * last arg.
4111 */
4112 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4113 line++;
4114 *line = '\0';
4115
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004116 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004117 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004118 err_code |= ERR_ALERT | ERR_FATAL;
4119 args[arg] = line;
4120 }
4121
Willy Tarreau540abe42007-05-02 20:50:16 +02004122 /* zero out remaining args and ensure that at least one entry
4123 * is zeroed out.
4124 */
4125 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 args[arg] = line;
4127 }
4128
Willy Tarreau3842f002009-06-14 11:39:52 +02004129 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004130 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004131 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004132 for (arg=0; *args[arg+1]; arg++)
4133 args[arg] = args[arg+1]; // shift args after inversion
4134 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004135 else if (!strcmp(args[0], "default")) {
4136 kwm = KWM_DEF;
4137 for (arg=0; *args[arg+1]; arg++)
4138 args[arg] = args[arg+1]; // shift args after inversion
4139 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004140
Willy Tarreau3842f002009-06-14 11:39:52 +02004141 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4142 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004143 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004144 }
4145
Willy Tarreau977b8e42006-12-29 14:19:17 +01004146 if (!strcmp(args[0], "listen") ||
4147 !strcmp(args[0], "frontend") ||
4148 !strcmp(args[0], "backend") ||
4149 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004150 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004152 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004153 cursection = strdup(args[0]);
4154 }
4155 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004157 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004158 cursection = strdup(args[0]);
4159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 /* else it's a section keyword */
4161
4162 switch (confsect) {
4163 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004164 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 break;
4166 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004167 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 break;
4169 default:
4170 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004171 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004173
4174 if (err_code & ERR_ABORT)
4175 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004177 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004178 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004180 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004181}
4182
Willy Tarreaubb925012009-07-23 13:36:36 +02004183/*
4184 * Returns the error code, 0 if OK, or any combination of :
4185 * - ERR_ABORT: must abort ASAP
4186 * - ERR_FATAL: we can continue parsing but not start the service
4187 * - ERR_WARN: a warning has been emitted
4188 * - ERR_ALERT: an alert has been emitted
4189 * Only the two first ones can stop processing, the two others are just
4190 * indicators.
4191 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004192int check_config_validity()
4193{
4194 int cfgerr = 0;
4195 struct proxy *curproxy = NULL;
4196 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004197 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004198 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199
4200 /*
4201 * Now, check for the integrity of all that we have collected.
4202 */
4203
4204 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004205 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004207 /* first, we will invert the proxy list order */
4208 curproxy = NULL;
4209 while (proxy) {
4210 struct proxy *next;
4211
4212 next = proxy->next;
4213 proxy->next = curproxy;
4214 curproxy = proxy;
4215 if (!next)
4216 break;
4217 proxy = next;
4218 }
4219
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004221 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 }
4225
4226 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004227 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004228 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004229 unsigned int next_id;
4230
4231 if (!curproxy->uuid) {
4232 /* proxy ID not set, use automatic numbering with first
4233 * spare entry starting with next_pxid.
4234 */
4235 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4236 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4237 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4238 next_pxid++;
4239 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004240
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004242 /* ensure we don't keep listeners uselessly bound */
4243 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 curproxy = curproxy->next;
4245 continue;
4246 }
4247
Willy Tarreauff01a212009-03-15 13:46:16 +01004248 switch (curproxy->mode) {
4249 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004250 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004251 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004252 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4253 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004254 cfgerr++;
4255 }
4256
4257 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004258 Warning("config : servers will be ignored for %s '%s'.\n",
4259 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004260 break;
4261
4262 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004263 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004264 break;
4265
4266 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004267 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004268 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004269 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4270 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004271 cfgerr++;
4272 }
4273 break;
4274 }
4275
4276 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004277 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4278 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 cfgerr++;
4280 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004281
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004282 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004283 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004284 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004285 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4286 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004287 cfgerr++;
4288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004290 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004291 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4292 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004293 cfgerr++;
4294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004296 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004297 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4298 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004299 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004300 }
4301 }
4302 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4303 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4304 /* If no LB algo is set in a backend, and we're not in
4305 * transparent mode, dispatch mode nor proxy mode, we
4306 * want to use balance roundrobin by default.
4307 */
4308 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4309 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 }
4311 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004312
Willy Tarreau82936582007-11-30 15:20:09 +01004313 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4314 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004315 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4316 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004317 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004318 }
4319
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004320 /* if a default backend was specified, let's find it */
4321 if (curproxy->defbe.name) {
4322 struct proxy *target;
4323
Alex Williams96532db2009-11-01 21:27:13 -05004324 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004325 if (!target) {
4326 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4327 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004328 cfgerr++;
4329 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004330 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4331 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004332 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004333 } else {
4334 free(curproxy->defbe.name);
4335 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004336 /* we force the backend to be present on at least all of
4337 * the frontend's processes.
4338 */
4339 target->bind_proc = curproxy->bind_proc ?
4340 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 }
4342 }
4343
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004344 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004345 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4346 /* map jump target for ACT_SETBE in req_rep chain */
4347 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004348 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004349 struct proxy *target;
4350
Willy Tarreaua496b602006-12-17 23:15:24 +01004351 if (exp->action != ACT_SETBE)
4352 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004353
Alex Williams96532db2009-11-01 21:27:13 -05004354 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004355 if (!target) {
4356 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4357 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004358 cfgerr++;
4359 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004360 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4361 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004362 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004363 } else {
4364 free((void *)exp->replace);
4365 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004366 /* we force the backend to be present on at least all of
4367 * the frontend's processes.
4368 */
4369 target->bind_proc = curproxy->bind_proc ?
4370 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004371 }
4372 }
4373 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004374
4375 /* find the target proxy for 'use_backend' rules */
4376 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004377 struct proxy *target;
4378
Alex Williams96532db2009-11-01 21:27:13 -05004379 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004380
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004381 if (!target) {
4382 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4383 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004384 cfgerr++;
4385 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004386 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4387 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004388 cfgerr++;
4389 } else {
4390 free((void *)rule->be.name);
4391 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004392 /* we force the backend to be present on at least all of
4393 * the frontend's processes.
4394 */
4395 target->bind_proc = curproxy->bind_proc ?
4396 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004397 }
4398 }
4399
Willy Tarreau2738a142006-07-08 17:28:09 +02004400 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004401 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004402 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004403 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004404 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004405 " | While not properly invalid, you will certainly encounter various problems\n"
4406 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004407 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004408 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004409 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004410 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004411
Willy Tarreau1fa31262007-12-03 00:36:16 +01004412 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4413 * We must still support older configurations, so let's find out whether those
4414 * parameters have been set or must be copied from contimeouts.
4415 */
4416 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004417 if (!curproxy->timeout.tarpit ||
4418 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004419 /* tarpit timeout not set. We search in the following order:
4420 * default.tarpit, curr.connect, default.connect.
4421 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004422 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004423 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004424 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004425 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004426 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004427 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004428 }
4429 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004430 (!curproxy->timeout.queue ||
4431 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004432 /* queue timeout not set. We search in the following order:
4433 * default.queue, curr.connect, default.connect.
4434 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004435 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004436 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004437 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004438 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004439 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004440 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004441 }
4442 }
4443
Willy Tarreauf3c69202006-07-09 16:42:34 +02004444 if (curproxy->options & PR_O_SSL3_CHK) {
4445 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4446 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4447 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4448 }
4449
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004450 /* The small pools required for the capture lists */
4451 if (curproxy->nb_req_cap)
4452 curproxy->req_cap_pool = create_pool("ptrcap",
4453 curproxy->nb_req_cap * sizeof(char *),
4454 MEM_F_SHARED);
4455 if (curproxy->nb_rsp_cap)
4456 curproxy->rsp_cap_pool = create_pool("ptrcap",
4457 curproxy->nb_rsp_cap * sizeof(char *),
4458 MEM_F_SHARED);
4459
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004460 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4461 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4462 MEM_F_SHARED);
4463
Willy Tarreau86034312006-12-29 00:10:33 +01004464 /* for backwards compatibility with "listen" instances, if
4465 * fullconn is not set but maxconn is set, then maxconn
4466 * is used.
4467 */
4468 if (!curproxy->fullconn)
4469 curproxy->fullconn = curproxy->maxconn;
4470
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 /* first, we will invert the servers list order */
4472 newsrv = NULL;
4473 while (curproxy->srv) {
4474 struct server *next;
4475
4476 next = curproxy->srv->next;
4477 curproxy->srv->next = newsrv;
4478 newsrv = curproxy->srv;
4479 if (!next)
4480 break;
4481 curproxy->srv = next;
4482 }
4483
Willy Tarreau20697042007-11-15 23:26:18 +01004484 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004485 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004487 /* We have to initialize the server lookup mechanism depending
4488 * on what LB algorithm was choosen.
4489 */
4490
4491 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4492 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4493 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004494 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4495 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4496 init_server_map(curproxy);
4497 } else {
4498 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4499 fwrr_init_server_groups(curproxy);
4500 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004501 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004502
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004503 case BE_LB_KIND_LC:
4504 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004505 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004506 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004507
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004508 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004509 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4510 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4511 chash_init_server_tree(curproxy);
4512 } else {
4513 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4514 init_server_map(curproxy);
4515 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004516 break;
4517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518
4519 if (curproxy->options & PR_O_LOGASAP)
4520 curproxy->to_log &= ~LW_BYTES;
4521
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004522 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4523 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4524 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4525 proxy_type_str(curproxy), curproxy->id);
4526 err_code |= ERR_WARN;
4527 }
4528
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004530 * ensure that we're not cross-dressing a TCP server into HTTP.
4531 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004532 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004533 newsrv = curproxy->srv;
4534 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004535 if (!newsrv->puid) {
4536 /* server ID not set, use automatic numbering with first
4537 * spare entry starting with next_svid.
4538 */
4539 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4540 newsrv->conf.id.key = newsrv->puid = next_id;
4541 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4542 next_id++;
4543 }
4544
Willy Tarreau21d2af32008-02-14 20:25:24 +01004545 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004546 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4547 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004548 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004549 }
4550 newsrv = newsrv->next;
4551 }
4552
4553 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004554 * If this server supports a maxconn parameter, it needs a dedicated
4555 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004556 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 */
4558 newsrv = curproxy->srv;
4559 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004560 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 /* Only 'minconn' was specified, or it was higher than or equal
4562 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4563 * this will avoid further useless expensive computations.
4564 */
4565 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004566 } else if (newsrv->maxconn && !newsrv->minconn) {
4567 /* minconn was not specified, so we set it to maxconn */
4568 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004569 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004570 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4571 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004572 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
4574
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004575 if (newsrv->trackit) {
4576 struct proxy *px;
4577 struct server *srv;
4578 char *pname, *sname;
4579
4580 pname = newsrv->trackit;
4581 sname = strrchr(pname, '/');
4582
4583 if (sname)
4584 *sname++ = '\0';
4585 else {
4586 sname = pname;
4587 pname = NULL;
4588 }
4589
4590 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004591 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004592 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004593 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4594 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004595 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004596 cfgerr++;
4597 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004598 }
4599 } else
4600 px = curproxy;
4601
4602 srv = findserver(px, sname);
4603 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004604 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4605 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004606 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004607 cfgerr++;
4608 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004609 }
4610
4611 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004612 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004613 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004614 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004615 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004616 cfgerr++;
4617 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004618 }
4619
4620 if (curproxy != px &&
4621 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004622 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004623 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004624 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004625 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004626 cfgerr++;
4627 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004628 }
4629
4630 newsrv->tracked = srv;
4631 newsrv->tracknext = srv->tracknext;
4632 srv->tracknext = newsrv;
4633
4634 free(newsrv->trackit);
4635 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004636 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 newsrv = newsrv->next;
4638 }
4639
Willy Tarreauc1a21672009-08-16 22:37:44 +02004640 if (curproxy->cap & PR_CAP_FE) {
4641 if (curproxy->tcp_req.inspect_delay ||
4642 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4643 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4644
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004645 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004646 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004647 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004648 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004649
4650 /* both TCP and HTTP must check switching rules */
4651 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4652 }
4653
4654 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004655 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004656 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004657 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004658 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004659
4660 /* If the backend does requires RDP cookie persistence, we have to
4661 * enable the corresponding analyser.
4662 */
4663 if (curproxy->options2 & PR_O2_RDPC_PRST)
4664 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4665 }
4666
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004667 listener = NULL;
4668 while (curproxy->listen) {
4669 struct listener *next;
4670
4671 next = curproxy->listen->next;
4672 curproxy->listen->next = listener;
4673 listener = curproxy->listen;
4674
4675 if (!next)
4676 break;
4677
4678 curproxy->listen = next;
4679 }
4680
Willy Tarreaue6b98942007-10-29 01:09:36 +01004681 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004682 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004683 listener = curproxy->listen;
4684 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004685 if (!listener->luid) {
4686 /* listener ID not set, use automatic numbering with first
4687 * spare entry starting with next_luid.
4688 */
4689 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4690 listener->conf.id.key = listener->luid = next_id;
4691 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4692 next_id++;
4693 }
4694
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004695 /* enable separate counters */
4696 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4697 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4698 if (!listener->name) {
4699 sprintf(trash, "sock-%d", listener->luid);
4700 listener->name = strdup(trash);
4701 }
4702 }
4703
Willy Tarreaue6b98942007-10-29 01:09:36 +01004704 if (curproxy->options & PR_O_TCP_NOLING)
4705 listener->options |= LI_O_NOLINGER;
4706 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004707 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004708 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004709 listener->accept = event_accept;
4710 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004711 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004712 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004713
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004714 /* smart accept mode is automatic in HTTP mode */
4715 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4716 (curproxy->mode == PR_MODE_HTTP &&
4717 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4718 listener->options |= LI_O_NOQUICKACK;
4719
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004720 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004721 listener = listener->next;
4722 }
4723
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 curproxy = curproxy->next;
4725 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004726
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004727 /*
4728 * Recount currently required checks.
4729 */
4730
4731 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4732 int optnum;
4733
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004734 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4735 if (curproxy->options & cfg_opts[optnum].val)
4736 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004737
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004738 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4739 if (curproxy->options2 & cfg_opts2[optnum].val)
4740 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004741 }
4742
Willy Tarreaubb925012009-07-23 13:36:36 +02004743 if (cfgerr > 0)
4744 err_code |= ERR_ALERT | ERR_FATAL;
4745 out:
4746 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747}
4748
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004749/*
4750 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4751 * parsing sessions.
4752 */
4753void cfg_register_keywords(struct cfg_kw_list *kwl)
4754{
4755 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4756}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004758/*
4759 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4760 */
4761void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4762{
4763 LIST_DEL(&kwl->list);
4764 LIST_INIT(&kwl->list);
4765}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766
4767/*
4768 * Local variables:
4769 * c-indent-level: 8
4770 * c-basic-offset: 8
4771 * End:
4772 */