blob: 58505ec27f95c6e0e0248a413a22e6ed009062ec [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 Tarreau81e3b4f2010-01-10 00:42:19 +01001851 else if (!strcmp(args[cur_arg],"append-slash")) {
1852 flags |= REDIRECT_FLAG_APPEND_SLASH;
1853 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001854 else if (!strcmp(args[cur_arg], "if")) {
1855 pol = ACL_COND_IF;
1856 cur_arg++;
1857 break;
1858 }
1859 else if (!strcmp(args[cur_arg], "unless")) {
1860 pol = ACL_COND_UNLESS;
1861 cur_arg++;
1862 break;
1863 }
1864 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001865 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001866 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001869 }
1870 cur_arg++;
1871 }
1872
1873 if (type == REDIRECT_TYPE_NONE) {
1874 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1875 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001878 }
1879
Willy Tarreauf285f542010-01-03 20:03:03 +01001880 if (pol != ACL_COND_NONE &&
1881 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001882 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001883 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001886 }
1887
Willy Tarreauf285f542010-01-03 20:03:03 +01001888 if (cond) {
1889 cond->file = file;
1890 cond->line = linenum;
1891 curproxy->acl_requires |= cond->requires;
1892 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001893 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1894 rule->cond = cond;
1895 rule->rdr_str = strdup(destination);
1896 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001897 if (cookie) {
1898 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1899 * a clear consists in appending "; Max-Age=0" at the end.
1900 */
1901 rule->cookie_len = strlen(cookie);
1902 if (cookie_set)
1903 rule->cookie_str = strdup(cookie);
1904 else {
1905 rule->cookie_str = malloc(rule->cookie_len + 12);
1906 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1907 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1908 rule->cookie_len += 11;
1909 }
1910 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001911 rule->type = type;
1912 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001913 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001914 LIST_INIT(&rule->list);
1915 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001916 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001917 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001918 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001919 int pol = ACL_COND_NONE;
1920 struct acl_cond *cond;
1921 struct switching_rule *rule;
1922
Willy Tarreaub099aca2008-10-12 17:26:37 +02001923 if (curproxy == &defproxy) {
1924 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001925 err_code |= ERR_ALERT | ERR_FATAL;
1926 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001927 }
1928
Willy Tarreau55ea7572007-06-17 19:56:27 +02001929 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001931
1932 if (*(args[1]) == 0) {
1933 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001936 }
1937
1938 if (!strcmp(args[2], "if"))
1939 pol = ACL_COND_IF;
1940 else if (!strcmp(args[2], "unless"))
1941 pol = ACL_COND_UNLESS;
1942
1943 if (pol == ACL_COND_NONE) {
1944 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1945 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001948 }
1949
1950 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001951 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001952 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001955 }
1956
Willy Tarreau88922352009-10-04 22:02:50 +02001957 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001958 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001959 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001960 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001961 struct acl *acl;
1962 const char *name;
1963
1964 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1965 name = acl ? acl->name : "(unknown)";
1966 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1967 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001968 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001969 }
1970
Willy Tarreau55ea7572007-06-17 19:56:27 +02001971 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1972 rule->cond = cond;
1973 rule->be.name = strdup(args[1]);
1974 LIST_INIT(&rule->list);
1975 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001978 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001979 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001980
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1982 curproxy->uri_auth = NULL; /* we must detach from the default config */
1983
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01001984 if (!*args[1]) {
1985 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 } else if (!strcmp(args[1], "uri")) {
1987 if (*(args[2]) == 0) {
1988 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1992 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001993 err_code |= ERR_ALERT | ERR_ABORT;
1994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 }
1996 } else if (!strcmp(args[1], "realm")) {
1997 if (*(args[2]) == 0) {
1998 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2002 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_ALERT | ERR_ABORT;
2004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002006 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002007 unsigned interval;
2008
2009 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2010 if (err) {
2011 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2012 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002013 err_code |= ERR_ALERT | ERR_FATAL;
2014 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002015 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_ABORT;
2018 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020 } else if (!strcmp(args[1], "auth")) {
2021 if (*(args[2]) == 0) {
2022 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002023 err_code |= ERR_ALERT | ERR_FATAL;
2024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002025 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2026 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_ABORT;
2028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 }
2030 } else if (!strcmp(args[1], "scope")) {
2031 if (*(args[2]) == 0) {
2032 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_ALERT | ERR_FATAL;
2034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2036 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002037 err_code |= ERR_ALERT | ERR_ABORT;
2038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 }
2040 } else if (!strcmp(args[1], "enable")) {
2041 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2042 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_ALERT | ERR_ABORT;
2044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002046 } else if (!strcmp(args[1], "hide-version")) {
2047 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002049 err_code |= ERR_ALERT | ERR_ABORT;
2050 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002051 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002052 } else if (!strcmp(args[1], "show-legends")) {
2053 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2054 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2055 err_code |= ERR_ALERT | ERR_ABORT;
2056 goto out;
2057 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002058 } else if (!strcmp(args[1], "show-node")) {
2059
2060 if (*args[2]) {
2061 int i;
2062 char c;
2063
2064 for (i=0; args[2][i]; i++) {
2065 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002066 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002067 break;
2068 }
2069
2070 if (!i || args[2][i]) {
2071 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2072 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2073 file, linenum, args[0], args[1]);
2074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
2076 }
2077 }
2078
2079 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2080 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2081 err_code |= ERR_ALERT | ERR_ABORT;
2082 goto out;
2083 }
2084 } else if (!strcmp(args[1], "show-desc")) {
2085 char *desc = NULL;
2086
2087 if (*args[2]) {
2088 int i, len=0;
2089 char *d;
2090
2091 for(i=2; *args[i]; i++)
2092 len += strlen(args[i])+1;
2093
2094 desc = d = (char *)calloc(1, len);
2095
2096 d += sprintf(d, "%s", args[2]);
2097 for(i=3; *args[i]; i++)
2098 d += sprintf(d, " %s", args[i]);
2099 }
2100
2101 if (!*args[2] && !global.desc)
2102 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2103 file, linenum, args[1]);
2104 else {
2105 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2106 free(desc);
2107 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2108 err_code |= ERR_ALERT | ERR_ABORT;
2109 goto out;
2110 }
2111 free(desc);
2112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002114stats_error_parsing:
2115 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2116 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 }
2120 }
2121 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002122 int optnum;
2123
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002124 if (*(args[1]) == '\0') {
2125 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2126 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002129 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002130
2131 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2132 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002133 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2134 err_code |= ERR_WARN;
2135 goto out;
2136 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002137
Willy Tarreau3842f002009-06-14 11:39:52 +02002138 curproxy->no_options &= ~cfg_opts[optnum].val;
2139 curproxy->options &= ~cfg_opts[optnum].val;
2140
2141 switch (kwm) {
2142 case KWM_STD:
2143 curproxy->options |= cfg_opts[optnum].val;
2144 break;
2145 case KWM_NO:
2146 curproxy->no_options |= cfg_opts[optnum].val;
2147 break;
2148 case KWM_DEF: /* already cleared */
2149 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002150 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002151
Willy Tarreau93893792009-07-23 13:19:11 +02002152 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002153 }
2154 }
2155
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002156 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2157 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002158 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2159 err_code |= ERR_WARN;
2160 goto out;
2161 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002162
Willy Tarreau3842f002009-06-14 11:39:52 +02002163 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2164 curproxy->options2 &= ~cfg_opts2[optnum].val;
2165
2166 switch (kwm) {
2167 case KWM_STD:
2168 curproxy->options2 |= cfg_opts2[optnum].val;
2169 break;
2170 case KWM_NO:
2171 curproxy->no_options2 |= cfg_opts2[optnum].val;
2172 break;
2173 case KWM_DEF: /* already cleared */
2174 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002175 }
Willy Tarreau93893792009-07-23 13:19:11 +02002176 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002177 }
2178 }
2179
Willy Tarreau3842f002009-06-14 11:39:52 +02002180 if (kwm != KWM_STD) {
2181 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002182 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002185 }
2186
Emeric Brun3a058f32009-06-30 18:26:00 +02002187 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002189 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002191 if (*(args[2]) != '\0') {
2192 if (!strcmp(args[2], "clf")) {
2193 curproxy->options2 |= PR_O2_CLFLOG;
2194 } else {
2195 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002198 }
2199 }
2200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 else if (!strcmp(args[1], "tcplog"))
2202 /* generate a detailed TCP log */
2203 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 else if (!strcmp(args[1], "tcpka")) {
2205 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002206 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002208
2209 if (curproxy->cap & PR_CAP_FE)
2210 curproxy->options |= PR_O_TCP_CLI_KA;
2211 if (curproxy->cap & PR_CAP_BE)
2212 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 }
2214 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_WARN;
2217
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002219 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002220 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002221 curproxy->options &= ~PR_O_SMTP_CHK;
2222 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002223 if (!*args[2]) { /* no argument */
2224 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2225 curproxy->check_len = strlen(DEF_CHECK_REQ);
2226 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002227 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 curproxy->check_req = (char *)malloc(reqlen);
2229 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2230 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2231 } else { /* more arguments : METHOD URI [HTTP_VER] */
2232 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2233 if (*args[4])
2234 reqlen += strlen(args[4]);
2235 else
2236 reqlen += strlen("HTTP/1.0");
2237
2238 curproxy->check_req = (char *)malloc(reqlen);
2239 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2240 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2241 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002242 }
2243 else if (!strcmp(args[1], "ssl-hello-chk")) {
2244 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002245 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002247
Willy Tarreaua534fea2008-08-03 12:19:50 +02002248 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002249 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002250 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002251 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 }
Willy Tarreau23677902007-05-08 23:50:35 +02002253 else if (!strcmp(args[1], "smtpchk")) {
2254 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002255 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002256 curproxy->options &= ~PR_O_HTTP_CHK;
2257 curproxy->options &= ~PR_O_SSL3_CHK;
2258 curproxy->options |= PR_O_SMTP_CHK;
2259
2260 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2261 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2262 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2263 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2264 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2265 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2266 curproxy->check_req = (char *)malloc(reqlen);
2267 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2268 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2269 } else {
2270 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2271 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2272 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2273 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2274 }
2275 }
2276 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002277 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002278 int cur_arg;
2279
2280 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2281 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002282 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002283
2284 curproxy->options |= PR_O_FWDFOR;
2285
2286 free(curproxy->fwdfor_hdr_name);
2287 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2288 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2289
2290 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2291 cur_arg = 2;
2292 while (*(args[cur_arg])) {
2293 if (!strcmp(args[cur_arg], "except")) {
2294 /* suboption except - needs additional argument for it */
2295 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2296 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2297 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002300 }
2301 /* flush useless bits */
2302 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002303 cur_arg += 2;
2304 } else if (!strcmp(args[cur_arg], "header")) {
2305 /* suboption header - needs additional argument for it */
2306 if (*(args[cur_arg+1]) == 0) {
2307 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2308 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002311 }
2312 free(curproxy->fwdfor_hdr_name);
2313 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2314 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2315 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002316 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002317 /* unknown suboption - catchall */
2318 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2319 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002322 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002323 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002324 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002325 else if (!strcmp(args[1], "originalto")) {
2326 int cur_arg;
2327
2328 /* insert x-original-to field, but not for the IP address listed as an except.
2329 * set default options (ie: bitfield, header name, etc)
2330 */
2331
2332 curproxy->options |= PR_O_ORGTO;
2333
2334 free(curproxy->orgto_hdr_name);
2335 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2336 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2337
2338 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2339 cur_arg = 2;
2340 while (*(args[cur_arg])) {
2341 if (!strcmp(args[cur_arg], "except")) {
2342 /* suboption except - needs additional argument for it */
2343 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2344 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2345 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002348 }
2349 /* flush useless bits */
2350 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2351 cur_arg += 2;
2352 } else if (!strcmp(args[cur_arg], "header")) {
2353 /* suboption header - needs additional argument for it */
2354 if (*(args[cur_arg+1]) == 0) {
2355 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2356 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002359 }
2360 free(curproxy->orgto_hdr_name);
2361 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2362 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2363 cur_arg += 2;
2364 } else {
2365 /* unknown suboption - catchall */
2366 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2367 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002370 }
2371 } /* end while loop */
2372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 else {
2374 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }
Willy Tarreau93893792009-07-23 13:19:11 +02002378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002380 else if (!strcmp(args[0], "default_backend")) {
2381 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002383
2384 if (*(args[1]) == 0) {
2385 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002388 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002389 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002390 curproxy->defbe.name = strdup(args[1]);
2391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002395
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002396 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 /* enable reconnections to dispatch */
2400 curproxy->options |= PR_O_REDISP;
2401 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002402 else if (!strcmp(args[0], "http-check")) {
2403 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002405
2406 if (strcmp(args[1], "disable-on-404") == 0) {
2407 /* enable a graceful server shutdown on an HTTP 404 response */
2408 curproxy->options |= PR_O_DISABLE404;
2409 }
2410 else {
2411 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002414 }
2415 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002416 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002417 if (curproxy == &defproxy) {
2418 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002421 }
2422
Willy Tarreaub80c2302007-11-30 20:51:32 +01002423 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002425
2426 if (strcmp(args[1], "fail") == 0) {
2427 /* add a condition to fail monitor requests */
2428 int pol = ACL_COND_NONE;
2429 struct acl_cond *cond;
2430
2431 if (!strcmp(args[2], "if"))
2432 pol = ACL_COND_IF;
2433 else if (!strcmp(args[2], "unless"))
2434 pol = ACL_COND_UNLESS;
2435
2436 if (pol == ACL_COND_NONE) {
2437 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2438 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002441 }
2442
2443 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2444 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2445 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002448 }
Willy Tarreau88922352009-10-04 22:02:50 +02002449 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002450 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002451 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002452 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2453 }
2454 else {
2455 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002458 }
2459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460#ifdef TPROXY
2461 else if (!strcmp(args[0], "transparent")) {
2462 /* enable transparent proxy connections */
2463 curproxy->options |= PR_O_TRANSP;
2464 }
2465#endif
2466 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002467 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 if (*(args[1]) == 0) {
2471 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 }
2475 curproxy->maxconn = atol(args[1]);
2476 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002477 else if (!strcmp(args[0], "backlog")) { /* backlog */
2478 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002480
2481 if (*(args[1]) == 0) {
2482 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002485 }
2486 curproxy->backlog = atol(args[1]);
2487 }
Willy Tarreau86034312006-12-29 00:10:33 +01002488 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002491
Willy Tarreau86034312006-12-29 00:10:33 +01002492 if (*(args[1]) == 0) {
2493 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002496 }
2497 curproxy->fullconn = atol(args[1]);
2498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2500 if (*(args[1]) == 0) {
2501 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002505 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2506 if (err) {
2507 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2508 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002511 }
2512 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 }
2514 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2515 if (curproxy == &defproxy) {
2516 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002520 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002522
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 if (strchr(args[1], ':') == NULL) {
2524 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
2528 curproxy->dispatch_addr = *str2sa(args[1]);
2529 }
2530 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002532 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002533
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002534 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002535 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2536 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002541 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2542 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2543 err_code |= ERR_WARN;
2544
2545 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2546 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2547 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2548 }
2549 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2550 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2551 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2552 }
2553 else {
2554 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
2557 }
2558 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002559 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002561 char *rport, *raddr;
2562 short realport = 0;
2563 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002565 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572
2573 if (!*args[2]) {
2574 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002579
2580 err = invalid_char(args[1]);
2581 if (err) {
2582 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2583 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002586 }
2587
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_ABORT;
2591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
2593
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002594 if (!defsrv) {
2595 /* the servers are linked backwards first */
2596 newsrv->next = curproxy->srv;
2597 curproxy->srv = newsrv;
2598 newsrv->proxy = curproxy;
2599 newsrv->conf.file = file;
2600 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002602 LIST_INIT(&newsrv->pendconns);
2603 do_check = 0;
2604 newsrv->state = SRV_RUNNING; /* early server setup */
2605 newsrv->last_change = now.tv_sec;
2606 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002608 /* several ways to check the port component :
2609 * - IP => port=+0, relative
2610 * - IP: => port=+0, relative
2611 * - IP:N => port=N, absolute
2612 * - IP:+N => port=+N, relative
2613 * - IP:-N => port=-N, relative
2614 */
2615 raddr = strdup(args[2]);
2616 rport = strchr(raddr, ':');
2617 if (rport) {
2618 *rport++ = 0;
2619 realport = atol(rport);
2620 if (!isdigit((unsigned char)*rport))
2621 newsrv->state |= SRV_MAPPORTS;
2622 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002624
2625 newsrv->addr = *str2sa(raddr);
2626 newsrv->addr.sin_port = htons(realport);
2627 free(raddr);
2628
2629 newsrv->check_port = curproxy->defsrv.check_port;
2630 newsrv->inter = curproxy->defsrv.inter;
2631 newsrv->fastinter = curproxy->defsrv.fastinter;
2632 newsrv->downinter = curproxy->defsrv.downinter;
2633 newsrv->rise = curproxy->defsrv.rise;
2634 newsrv->fall = curproxy->defsrv.fall;
2635 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2636 newsrv->minconn = curproxy->defsrv.minconn;
2637 newsrv->maxconn = curproxy->defsrv.maxconn;
2638 newsrv->slowstart = curproxy->defsrv.slowstart;
2639 newsrv->onerror = curproxy->defsrv.onerror;
2640 newsrv->consecutive_errors_limit
2641 = curproxy->defsrv.consecutive_errors_limit;
2642 newsrv->uweight = newsrv->iweight
2643 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002645 newsrv->curfd = -1; /* no health-check in progress */
2646 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002648 cur_arg = 3;
2649 } else {
2650 newsrv = &curproxy->defsrv;
2651 cur_arg = 1;
2652 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002653
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002655 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002656 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002657
2658 if (!*args[cur_arg + 1]) {
2659 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2660 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002663 }
2664
2665 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002666 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002667
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002668 if (newsrv->puid <= 0) {
2669 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002670 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002673 }
2674
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002675 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2676 if (node) {
2677 struct server *target = container_of(node, struct server, conf.id);
2678 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2679 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
2682 }
2683 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002684 cur_arg += 2;
2685 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002686 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 newsrv->cookie = strdup(args[cur_arg + 1]);
2688 newsrv->cklen = strlen(args[cur_arg + 1]);
2689 cur_arg += 2;
2690 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002691 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01002692 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2693 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2694 cur_arg += 2;
2695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002697 if (!*args[cur_arg + 1]) {
2698 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2699 file, linenum, args[cur_arg]);
2700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
2702 }
2703
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002705 if (newsrv->rise <= 0) {
2706 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2707 file, linenum, args[cur_arg]);
2708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
2710 }
2711
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 newsrv->health = newsrv->rise;
2713 cur_arg += 2;
2714 }
2715 else if (!strcmp(args[cur_arg], "fall")) {
2716 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002717
2718 if (!*args[cur_arg + 1]) {
2719 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2720 file, linenum, args[cur_arg]);
2721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
2723 }
2724
2725 if (newsrv->fall <= 0) {
2726 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2727 file, linenum, args[cur_arg]);
2728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
2730 }
2731
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 cur_arg += 2;
2733 }
2734 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002735 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2736 if (err) {
2737 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2738 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002741 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002742 if (val <= 0) {
2743 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2744 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002747 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002748 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 cur_arg += 2;
2750 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002751 else if (!strcmp(args[cur_arg], "fastinter")) {
2752 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2753 if (err) {
2754 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2755 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002758 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002759 if (val <= 0) {
2760 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2761 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002764 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002765 newsrv->fastinter = val;
2766 cur_arg += 2;
2767 }
2768 else if (!strcmp(args[cur_arg], "downinter")) {
2769 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2770 if (err) {
2771 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2772 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002775 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002776 if (val <= 0) {
2777 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2778 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002781 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002782 newsrv->downinter = val;
2783 cur_arg += 2;
2784 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002785 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002786 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002787 cur_arg += 2;
2788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 else if (!strcmp(args[cur_arg], "port")) {
2790 newsrv->check_port = atol(args[cur_arg + 1]);
2791 cur_arg += 2;
2792 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002793 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 newsrv->state |= SRV_BACKUP;
2795 cur_arg ++;
2796 }
2797 else if (!strcmp(args[cur_arg], "weight")) {
2798 int w;
2799 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002800 if (w < 0 || w > 256) {
2801 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002806 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 cur_arg += 2;
2808 }
2809 else if (!strcmp(args[cur_arg], "minconn")) {
2810 newsrv->minconn = atol(args[cur_arg + 1]);
2811 cur_arg += 2;
2812 }
2813 else if (!strcmp(args[cur_arg], "maxconn")) {
2814 newsrv->maxconn = atol(args[cur_arg + 1]);
2815 cur_arg += 2;
2816 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002817 else if (!strcmp(args[cur_arg], "maxqueue")) {
2818 newsrv->maxqueue = atol(args[cur_arg + 1]);
2819 cur_arg += 2;
2820 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002821 else if (!strcmp(args[cur_arg], "slowstart")) {
2822 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002823 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002824 if (err) {
2825 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2826 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002829 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002830 if (val <= 0) {
2831 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2832 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002835 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002836 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002837 cur_arg += 2;
2838 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002839 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002840
2841 if (!*args[cur_arg + 1]) {
2842 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2843 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002846 }
2847
2848 newsrv->trackit = strdup(args[cur_arg + 1]);
2849
2850 cur_arg += 2;
2851 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002852 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 global.maxsock++;
2854 do_check = 1;
2855 cur_arg += 1;
2856 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002857 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002858 if (!strcmp(args[cur_arg + 1], "none"))
2859 newsrv->observe = HANA_OBS_NONE;
2860 else if (!strcmp(args[cur_arg + 1], "layer4"))
2861 newsrv->observe = HANA_OBS_LAYER4;
2862 else if (!strcmp(args[cur_arg + 1], "layer7")) {
2863 if (curproxy->mode != PR_MODE_HTTP) {
2864 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
2865 file, linenum, args[cur_arg + 1]);
2866 err_code |= ERR_ALERT;
2867 }
2868 newsrv->observe = HANA_OBS_LAYER7;
2869 }
2870 else {
2871 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
2872 "'l4events', 'http-responses' but get '%s'\n",
2873 file, linenum, args[cur_arg], args[cur_arg + 1]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877
2878 cur_arg += 2;
2879 }
2880 else if (!strcmp(args[cur_arg], "on-error")) {
2881 if (!strcmp(args[cur_arg + 1], "fastinter"))
2882 newsrv->onerror = HANA_ONERR_FASTINTER;
2883 else if (!strcmp(args[cur_arg + 1], "fail-check"))
2884 newsrv->onerror = HANA_ONERR_FAILCHK;
2885 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
2886 newsrv->onerror = HANA_ONERR_SUDDTH;
2887 else if (!strcmp(args[cur_arg + 1], "mark-down"))
2888 newsrv->onerror = HANA_ONERR_MARKDWN;
2889 else {
2890 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
2891 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
2892 file, linenum, args[cur_arg], args[cur_arg + 1]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 cur_arg += 2;
2898 }
2899 else if (!strcmp(args[cur_arg], "error-limit")) {
2900 if (!*args[cur_arg + 1]) {
2901 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2902 file, linenum, args[cur_arg]);
2903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906
2907 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
2908
2909 if (newsrv->consecutive_errors_limit <= 0) {
2910 Alert("parsing [%s:%d]: %s has to be > 0.\n",
2911 file, linenum, args[cur_arg]);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002916 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002917 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002919#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002920 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002921 file, linenum, "source", "usesrc");
2922#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002923 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002925#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
2929 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002930 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2931
2932 if (port_low != port_high) {
2933 int i;
2934 if (port_low <= 0 || port_low > 65535 ||
2935 port_high <= 0 || port_high > 65535 ||
2936 port_low > port_high) {
2937 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2938 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002941 }
2942 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2943 for (i = 0; i < newsrv->sport_range->size; i++)
2944 newsrv->sport_range->ports[i] = port_low + i;
2945 }
2946
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002948 while (*(args[cur_arg])) {
2949 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002950#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2951#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002952 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2953 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2954 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002957 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002958#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002959 if (!*args[cur_arg + 1]) {
2960 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2961 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002964 }
2965 if (!strcmp(args[cur_arg + 1], "client")) {
2966 newsrv->state |= SRV_TPROXY_CLI;
2967 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2968 newsrv->state |= SRV_TPROXY_CIP;
2969 } else {
2970 newsrv->state |= SRV_TPROXY_ADDR;
2971 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2972 }
2973 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002974#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002975 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002976#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002977 cur_arg += 2;
2978 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002979#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002980 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002981 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002984#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2985 } /* "usesrc" */
2986
2987 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2988#ifdef SO_BINDTODEVICE
2989 if (!*args[cur_arg + 1]) {
2990 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2991 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002994 }
2995 if (newsrv->iface_name)
2996 free(newsrv->iface_name);
2997
2998 newsrv->iface_name = strdup(args[cur_arg + 1]);
2999 newsrv->iface_len = strlen(newsrv->iface_name);
3000 global.last_checks |= LSTCHK_NETADM;
3001#else
3002 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3003 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003006#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003007 cur_arg += 2;
3008 continue;
3009 }
3010 /* this keyword in not an option of "source" */
3011 break;
3012 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003014 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003015 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3016 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003021 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003022 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 +01003023 file, linenum, newsrv->id);
3024 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003025 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 +01003026 file, linenum);
3027
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003030 }
3031 }
3032
3033 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003034 if (newsrv->trackit) {
3035 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3036 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003039 }
3040
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003041 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3042 newsrv->check_port = newsrv->check_addr.sin_port;
3043
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3045 newsrv->check_port = realport; /* by default */
3046 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003047 /* not yet valid, because no port was set on
3048 * the server either. We'll check if we have
3049 * a known port on the first listener.
3050 */
3051 struct listener *l;
3052 l = curproxy->listen;
3053 if (l) {
3054 int port;
3055 port = (l->addr.ss_family == AF_INET6)
3056 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3057 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3058 newsrv->check_port = port;
3059 }
3060 }
3061 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3063 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003067
3068 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 newsrv->state |= SRV_CHECKED;
3070 }
3071
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003072 if (!defsrv) {
3073 if (newsrv->state & SRV_BACKUP)
3074 curproxy->srv_bck++;
3075 else
3076 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003077
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003078 newsrv->prev_state = newsrv->state;
3079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
3081 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003082 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 int facility;
3084
3085 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3086 curproxy->logfac1 = global.logfac1;
3087 curproxy->logsrv1 = global.logsrv1;
3088 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003089 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 curproxy->logfac2 = global.logfac2;
3091 curproxy->logsrv2 = global.logsrv2;
3092 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003093 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 }
3095 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003096 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097
3098 facility = get_log_facility(args[2]);
3099 if (facility < 0) {
3100 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3101 exit(1);
3102 }
3103
3104 level = 7; /* max syslog level = debug */
3105 if (*(args[3])) {
3106 level = get_log_level(args[3]);
3107 if (level < 0) {
3108 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3109 exit(1);
3110 }
3111 }
3112
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003113 minlvl = 0; /* limit syslog level to this level (emerg) */
3114 if (*(args[4])) {
3115 minlvl = get_log_level(args[4]);
3116 if (level < 0) {
3117 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3118 exit(1);
3119 }
3120 }
3121
Robert Tsai81ae1952007-12-05 10:47:29 +01003122 if (args[1][0] == '/') {
3123 logsrv.u.addr.sa_family = AF_UNIX;
3124 logsrv.u.un = *str2sun(args[1]);
3125 } else {
3126 logsrv.u.addr.sa_family = AF_INET;
3127 logsrv.u.in = *str2sa(args[1]);
3128 if (!logsrv.u.in.sin_port) {
3129 logsrv.u.in.sin_port =
3130 htons(SYSLOG_PORT);
3131 }
3132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133
3134 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003135 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 curproxy->logfac1 = facility;
3137 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003138 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 }
3140 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003141 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 curproxy->logfac2 = facility;
3143 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003144 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
3146 else {
3147 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 }
3151 }
3152 else {
3153 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3154 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 }
3158 }
3159 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003160 int cur_arg;
3161
Willy Tarreau977b8e42006-12-29 14:19:17 +01003162 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003164
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003166 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3167 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003171
3172 /* we must first clear any optional default setting */
3173 curproxy->options &= ~PR_O_TPXY_MASK;
3174 free(curproxy->iface_name);
3175 curproxy->iface_name = NULL;
3176 curproxy->iface_len = 0;
3177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 curproxy->source_addr = *str2sa(args[1]);
3179 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003180
3181 cur_arg = 2;
3182 while (*(args[cur_arg])) {
3183 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003184#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3185#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003186 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3187 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3188 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003191 }
3192#endif
3193 if (!*args[cur_arg + 1]) {
3194 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3195 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003198 }
3199
3200 if (!strcmp(args[cur_arg + 1], "client")) {
3201 curproxy->options |= PR_O_TPXY_CLI;
3202 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3203 curproxy->options |= PR_O_TPXY_CIP;
3204 } else {
3205 curproxy->options |= PR_O_TPXY_ADDR;
3206 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3207 }
3208 global.last_checks |= LSTCHK_NETADM;
3209#if !defined(CONFIG_HAP_LINUX_TPROXY)
3210 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003211#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003212#else /* no TPROXY support */
3213 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003214 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003217#endif
3218 cur_arg += 2;
3219 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003220 }
3221
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003222 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3223#ifdef SO_BINDTODEVICE
3224 if (!*args[cur_arg + 1]) {
3225 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3226 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003229 }
3230 if (curproxy->iface_name)
3231 free(curproxy->iface_name);
3232
3233 curproxy->iface_name = strdup(args[cur_arg + 1]);
3234 curproxy->iface_len = strlen(curproxy->iface_name);
3235 global.last_checks |= LSTCHK_NETADM;
3236#else
3237 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3238 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003241#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003242 cur_arg += 2;
3243 continue;
3244 }
3245 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3246 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003251 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3252 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3253 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3258 regex_t *preg;
3259 if (curproxy == &defproxy) {
3260 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003264 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003266
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 if (*(args[1]) == 0 || *(args[2]) == 0) {
3268 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3269 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 }
3273
3274 preg = calloc(1, sizeof(regex_t));
3275 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3276 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 }
3280
3281 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3282 if (err) {
3283 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3284 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003287 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
3289 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3290 regex_t *preg;
3291 if (curproxy == &defproxy) {
3292 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003296 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003298
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 if (*(args[1]) == 0) {
3300 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
3304
3305 preg = calloc(1, sizeof(regex_t));
3306 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3307 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311
3312 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003313 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
3315 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3316 regex_t *preg;
3317 if (curproxy == &defproxy) {
3318 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003322 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003324
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 if (*(args[1]) == 0) {
3326 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
3330
3331 preg = calloc(1, sizeof(regex_t));
3332 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3333 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 }
3337
3338 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003339 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
3341 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3342 regex_t *preg;
3343 if (curproxy == &defproxy) {
3344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003348 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003350
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 if (*(args[1]) == 0) {
3352 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
3356
3357 preg = calloc(1, sizeof(regex_t));
3358 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3359 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
3363
3364 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003365 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
3367 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3368 regex_t *preg;
3369 if (curproxy == &defproxy) {
3370 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003374 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003376
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 if (*(args[1]) == 0) {
3378 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 }
3382
3383 preg = calloc(1, sizeof(regex_t));
3384 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3385 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 }
3389
3390 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003391 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003393 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3394 regex_t *preg;
3395 if (curproxy == &defproxy) {
3396 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003399 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003400 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003402
Willy Tarreaub8750a82006-09-03 09:56:00 +02003403 if (*(args[1]) == 0) {
3404 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003407 }
3408
3409 preg = calloc(1, sizeof(regex_t));
3410 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3411 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003414 }
3415
3416 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003417 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003418 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003419 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3420 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003421 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003422 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003426 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003427 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003428
Willy Tarreau977b8e42006-12-29 14:19:17 +01003429 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003430 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3431 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003434 }
3435
3436 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003437 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003438 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003441 }
3442
3443 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003444 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003445 }
3446 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3447 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003448 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003449 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003452 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003453 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003455
Willy Tarreau977b8e42006-12-29 14:19:17 +01003456 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003457 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003461 }
3462
3463 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003464 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003465 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003468 }
3469
3470 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003471 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3474 regex_t *preg;
3475 if (curproxy == &defproxy) {
3476 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003480 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003482
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 if (*(args[1]) == 0 || *(args[2]) == 0) {
3484 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3485 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003486 err_code |= ERR_ALERT | ERR_FATAL;
3487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003488 }
3489
3490 preg = calloc(1, sizeof(regex_t));
3491 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3492 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 }
3496
3497 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3498 if (err) {
3499 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3500 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003504 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 }
3506 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3507 regex_t *preg;
3508 if (curproxy == &defproxy) {
3509 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003513 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003514 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003515
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 if (*(args[1]) == 0) {
3517 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
3521
3522 preg = calloc(1, sizeof(regex_t));
3523 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3524 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 }
3528
3529 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003530 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 }
3532 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3533 regex_t *preg;
3534 if (curproxy == &defproxy) {
3535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003539 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003541
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 if (*(args[1]) == 0) {
3543 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
3547
3548 preg = calloc(1, sizeof(regex_t));
3549 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3550 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }
3554
3555 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003556 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 }
3558 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3559 regex_t *preg;
3560 if (curproxy == &defproxy) {
3561 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003565 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003567
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568 if (*(args[1]) == 0) {
3569 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
3573
3574 preg = calloc(1, sizeof(regex_t));
3575 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3576 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 }
3580
3581 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003582 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 }
3584 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3585 regex_t *preg;
3586 if (curproxy == &defproxy) {
3587 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003591 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003593
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 if (*(args[1]) == 0) {
3595 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
3599
3600 preg = calloc(1, sizeof(regex_t));
3601 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3602 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
3606
3607 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003608 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003610 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3611 regex_t *preg;
3612 if (curproxy == &defproxy) {
3613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003617 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003619
Willy Tarreaub8750a82006-09-03 09:56:00 +02003620 if (*(args[1]) == 0) {
3621 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003624 }
3625
3626 preg = calloc(1, sizeof(regex_t));
3627 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3628 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003631 }
3632
3633 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003634 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003637 struct wordlist *wl;
3638
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 if (curproxy == &defproxy) {
3640 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003644 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 if (*(args[1]) == 0) {
3648 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003652
3653 wl = calloc(1, sizeof(*wl));
3654 wl->s = strdup(args[1]);
3655 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003656 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 }
3658 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3659 regex_t *preg;
3660
3661 if (*(args[1]) == 0 || *(args[2]) == 0) {
3662 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3663 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003667 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003669
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 preg = calloc(1, sizeof(regex_t));
3671 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3672 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 }
3676
3677 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3678 if (err) {
3679 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3680 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003684 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 }
3686 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3687 regex_t *preg;
3688 if (curproxy == &defproxy) {
3689 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003693 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003694 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003695
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 if (*(args[1]) == 0) {
3697 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 }
3701
3702 preg = calloc(1, sizeof(regex_t));
3703 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3704 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 }
3708
3709 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3710 if (err) {
3711 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3712 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
3716 }
3717 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3718 regex_t *preg;
3719 if (curproxy == &defproxy) {
3720 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003724 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003726
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727 if (*(args[1]) == 0) {
3728 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 }
3732
3733 preg = calloc(1, sizeof(regex_t));
3734 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3735 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 }
3739
3740 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3741 if (err) {
3742 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3743 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 }
3747 }
3748 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3749 regex_t *preg;
3750 if (curproxy == &defproxy) {
3751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003755 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757
3758 if (*(args[1]) == 0 || *(args[2]) == 0) {
3759 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3760 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763 }
3764
3765 preg = calloc(1, sizeof(regex_t));
3766 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3767 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770 }
3771
3772 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3773 if (err) {
3774 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3775 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
3779 }
3780 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3781 regex_t *preg;
3782 if (curproxy == &defproxy) {
3783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003787 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003789
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 if (*(args[1]) == 0) {
3791 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 }
3795
3796 preg = calloc(1, sizeof(regex_t));
3797 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3798 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 }
3802
3803 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3804 if (err) {
3805 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3806 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810 }
3811 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3812 regex_t *preg;
3813 if (curproxy == &defproxy) {
3814 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003818 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003820
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 if (*(args[1]) == 0) {
3822 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 }
3826
3827 preg = calloc(1, sizeof(regex_t));
3828 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3829 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 }
3833
3834 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3835 if (err) {
3836 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3837 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 }
3841 }
3842 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003843 struct wordlist *wl;
3844
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 if (curproxy == &defproxy) {
3846 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003850 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 if (*(args[1]) == 0) {
3854 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
3858
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003859 wl = calloc(1, sizeof(*wl));
3860 wl->s = strdup(args[1]);
3861 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 }
3863 else if (!strcmp(args[0], "errorloc") ||
3864 !strcmp(args[0], "errorloc302") ||
3865 !strcmp(args[0], "errorloc303")) { /* error location */
3866 int errnum, errlen;
3867 char *err;
3868
Willy Tarreau977b8e42006-12-29 14:19:17 +01003869 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003871
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003873 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
3877
3878 errnum = atol(args[1]);
3879 if (!strcmp(args[0], "errorloc303")) {
3880 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3881 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3882 } else {
3883 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3884 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3885 }
3886
Willy Tarreau0f772532006-12-23 20:51:41 +01003887 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3888 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003889 chunk_destroy(&curproxy->errmsg[rc]);
3890 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003891 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003894
3895 if (rc >= HTTP_ERR_SIZE) {
3896 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3897 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 free(err);
3899 }
3900 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003901 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3902 int errnum, errlen, fd;
3903 char *err;
3904 struct stat stat;
3905
3906 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003908
3909 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003910 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003913 }
3914
3915 fd = open(args[2], O_RDONLY);
3916 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3917 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3918 file, linenum, args[2], args[1]);
3919 if (fd >= 0)
3920 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003923 }
3924
Willy Tarreau27a674e2009-08-17 07:23:33 +02003925 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003926 errlen = stat.st_size;
3927 } else {
3928 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003929 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003931 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003932 }
3933
3934 err = malloc(errlen); /* malloc() must succeed during parsing */
3935 errnum = read(fd, err, errlen);
3936 if (errnum != errlen) {
3937 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3938 file, linenum, args[2], args[1]);
3939 close(fd);
3940 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003943 }
3944 close(fd);
3945
3946 errnum = atol(args[1]);
3947 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3948 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003949 chunk_destroy(&curproxy->errmsg[rc]);
3950 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003951 break;
3952 }
3953 }
3954
3955 if (rc >= HTTP_ERR_SIZE) {
3956 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3957 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003959 free(err);
3960 }
3961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003963 struct cfg_kw_list *kwl;
3964 int index;
3965
3966 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3967 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3968 if (kwl->kw[index].section != CFG_LISTEN)
3969 continue;
3970 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3971 /* prepare error message just in case */
3972 snprintf(trash, sizeof(trash),
3973 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003974 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3975 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003976 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003979 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003980 else if (rc > 0) {
3981 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003982 err_code |= ERR_WARN;
3983 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003984 }
Willy Tarreau93893792009-07-23 13:19:11 +02003985 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003986 }
3987 }
3988 }
3989
Willy Tarreau6daf3432008-01-22 16:44:08 +01003990 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 }
Willy Tarreau93893792009-07-23 13:19:11 +02003994 out:
3995 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996}
3997
3998
3999/*
4000 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004001 * Returns the error code, 0 if OK, or any combination of :
4002 * - ERR_ABORT: must abort ASAP
4003 * - ERR_FATAL: we can continue parsing but not start the service
4004 * - ERR_WARN: a warning has been emitted
4005 * - ERR_ALERT: an alert has been emitted
4006 * Only the two first ones can stop processing, the two others are just
4007 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004009int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004011 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 FILE *f;
4013 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004015 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 if ((f=fopen(file,"r")) == NULL)
4018 return -1;
4019
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004020 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004021 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004022 char *end;
4023 char *args[MAX_LINE_ARGS + 1];
4024 char *line = thisline;
4025
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026 linenum++;
4027
4028 end = line + strlen(line);
4029
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004030 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4031 /* Check if we reached the limit and the last char is not \n.
4032 * Watch out for the last line without the terminating '\n'!
4033 */
4034 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004035 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004037 }
4038
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004040 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 line++;
4042
4043 arg = 0;
4044 args[arg] = line;
4045
4046 while (*line && arg < MAX_LINE_ARGS) {
4047 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4048 * C equivalent value. Other combinations left unchanged (eg: \1).
4049 */
4050 if (*line == '\\') {
4051 int skip = 0;
4052 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4053 *line = line[1];
4054 skip = 1;
4055 }
4056 else if (line[1] == 'r') {
4057 *line = '\r';
4058 skip = 1;
4059 }
4060 else if (line[1] == 'n') {
4061 *line = '\n';
4062 skip = 1;
4063 }
4064 else if (line[1] == 't') {
4065 *line = '\t';
4066 skip = 1;
4067 }
4068 else if (line[1] == 'x') {
4069 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
4070 unsigned char hex1, hex2;
4071 hex1 = toupper(line[2]) - '0';
4072 hex2 = toupper(line[3]) - '0';
4073 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4074 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4075 *line = (hex1<<4) + hex2;
4076 skip = 3;
4077 }
4078 else {
4079 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 }
4082 }
4083 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004084 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004085 end -= skip;
4086 }
4087 line++;
4088 }
4089 else if (*line == '#' || *line == '\n' || *line == '\r') {
4090 /* end of string, end of loop */
4091 *line = 0;
4092 break;
4093 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004094 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004095 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004096 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004097 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098 line++;
4099 args[++arg] = line;
4100 }
4101 else {
4102 line++;
4103 }
4104 }
4105
4106 /* empty line */
4107 if (!**args)
4108 continue;
4109
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004110 if (*line) {
4111 /* we had to stop due to too many args.
4112 * Let's terminate the string, print the offending part then cut the
4113 * last arg.
4114 */
4115 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4116 line++;
4117 *line = '\0';
4118
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004119 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004120 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 args[arg] = line;
4123 }
4124
Willy Tarreau540abe42007-05-02 20:50:16 +02004125 /* zero out remaining args and ensure that at least one entry
4126 * is zeroed out.
4127 */
4128 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 args[arg] = line;
4130 }
4131
Willy Tarreau3842f002009-06-14 11:39:52 +02004132 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004133 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004134 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004135 for (arg=0; *args[arg+1]; arg++)
4136 args[arg] = args[arg+1]; // shift args after inversion
4137 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004138 else if (!strcmp(args[0], "default")) {
4139 kwm = KWM_DEF;
4140 for (arg=0; *args[arg+1]; arg++)
4141 args[arg] = args[arg+1]; // shift args after inversion
4142 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004143
Willy Tarreau3842f002009-06-14 11:39:52 +02004144 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4145 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004146 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004147 }
4148
Willy Tarreau977b8e42006-12-29 14:19:17 +01004149 if (!strcmp(args[0], "listen") ||
4150 !strcmp(args[0], "frontend") ||
4151 !strcmp(args[0], "backend") ||
4152 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004153 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004155 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004156 cursection = strdup(args[0]);
4157 }
4158 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004160 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004161 cursection = strdup(args[0]);
4162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 /* else it's a section keyword */
4164
4165 switch (confsect) {
4166 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004167 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 break;
4169 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004170 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 break;
4172 default:
4173 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004176
4177 if (err_code & ERR_ABORT)
4178 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004180 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004181 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004183 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004184}
4185
Willy Tarreaubb925012009-07-23 13:36:36 +02004186/*
4187 * Returns the error code, 0 if OK, or any combination of :
4188 * - ERR_ABORT: must abort ASAP
4189 * - ERR_FATAL: we can continue parsing but not start the service
4190 * - ERR_WARN: a warning has been emitted
4191 * - ERR_ALERT: an alert has been emitted
4192 * Only the two first ones can stop processing, the two others are just
4193 * indicators.
4194 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004195int check_config_validity()
4196{
4197 int cfgerr = 0;
4198 struct proxy *curproxy = NULL;
4199 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004200 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004201 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202
4203 /*
4204 * Now, check for the integrity of all that we have collected.
4205 */
4206
4207 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004208 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004210 /* first, we will invert the proxy list order */
4211 curproxy = NULL;
4212 while (proxy) {
4213 struct proxy *next;
4214
4215 next = proxy->next;
4216 proxy->next = curproxy;
4217 curproxy = proxy;
4218 if (!next)
4219 break;
4220 proxy = next;
4221 }
4222
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004224 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 }
4228
4229 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004230 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004231 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004232 unsigned int next_id;
4233
4234 if (!curproxy->uuid) {
4235 /* proxy ID not set, use automatic numbering with first
4236 * spare entry starting with next_pxid.
4237 */
4238 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4239 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4240 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4241 next_pxid++;
4242 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004243
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004245 /* ensure we don't keep listeners uselessly bound */
4246 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 curproxy = curproxy->next;
4248 continue;
4249 }
4250
Willy Tarreauff01a212009-03-15 13:46:16 +01004251 switch (curproxy->mode) {
4252 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004253 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004254 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004255 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4256 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004257 cfgerr++;
4258 }
4259
4260 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004261 Warning("config : servers will be ignored for %s '%s'.\n",
4262 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004263 break;
4264
4265 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004266 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004267 break;
4268
4269 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004270 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004271 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004272 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4273 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004274 cfgerr++;
4275 }
4276 break;
4277 }
4278
4279 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004280 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4281 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 cfgerr++;
4283 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004284
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004285 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004286 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004287 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004288 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4289 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004290 cfgerr++;
4291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004293 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004294 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4295 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004296 cfgerr++;
4297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004299 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004300 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4301 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004302 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004303 }
4304 }
4305 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4306 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4307 /* If no LB algo is set in a backend, and we're not in
4308 * transparent mode, dispatch mode nor proxy mode, we
4309 * want to use balance roundrobin by default.
4310 */
4311 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4312 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004313 }
4314 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004315
Willy Tarreau82936582007-11-30 15:20:09 +01004316 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4317 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004318 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4319 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004320 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004321 }
4322
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004323 /* if a default backend was specified, let's find it */
4324 if (curproxy->defbe.name) {
4325 struct proxy *target;
4326
Alex Williams96532db2009-11-01 21:27:13 -05004327 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004328 if (!target) {
4329 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4330 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004331 cfgerr++;
4332 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004333 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4334 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004335 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004336 } else {
4337 free(curproxy->defbe.name);
4338 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004339 /* we force the backend to be present on at least all of
4340 * the frontend's processes.
4341 */
4342 target->bind_proc = curproxy->bind_proc ?
4343 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 }
4345 }
4346
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004347 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004348 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4349 /* map jump target for ACT_SETBE in req_rep chain */
4350 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004351 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004352 struct proxy *target;
4353
Willy Tarreaua496b602006-12-17 23:15:24 +01004354 if (exp->action != ACT_SETBE)
4355 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004356
Alex Williams96532db2009-11-01 21:27:13 -05004357 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004358 if (!target) {
4359 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4360 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004361 cfgerr++;
4362 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004363 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4364 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004365 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004366 } else {
4367 free((void *)exp->replace);
4368 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004369 /* we force the backend to be present on at least all of
4370 * the frontend's processes.
4371 */
4372 target->bind_proc = curproxy->bind_proc ?
4373 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004374 }
4375 }
4376 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004377
4378 /* find the target proxy for 'use_backend' rules */
4379 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004380 struct proxy *target;
4381
Alex Williams96532db2009-11-01 21:27:13 -05004382 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004383
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004384 if (!target) {
4385 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4386 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004387 cfgerr++;
4388 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004389 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4390 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004391 cfgerr++;
4392 } else {
4393 free((void *)rule->be.name);
4394 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004395 /* we force the backend to be present on at least all of
4396 * the frontend's processes.
4397 */
4398 target->bind_proc = curproxy->bind_proc ?
4399 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004400 }
4401 }
4402
Willy Tarreau2738a142006-07-08 17:28:09 +02004403 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004404 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004405 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004406 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004407 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004408 " | While not properly invalid, you will certainly encounter various problems\n"
4409 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004410 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004411 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004412 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004413 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004414
Willy Tarreau1fa31262007-12-03 00:36:16 +01004415 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4416 * We must still support older configurations, so let's find out whether those
4417 * parameters have been set or must be copied from contimeouts.
4418 */
4419 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004420 if (!curproxy->timeout.tarpit ||
4421 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004422 /* tarpit timeout not set. We search in the following order:
4423 * default.tarpit, curr.connect, default.connect.
4424 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004425 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004426 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004427 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004428 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004429 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004430 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004431 }
4432 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004433 (!curproxy->timeout.queue ||
4434 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004435 /* queue timeout not set. We search in the following order:
4436 * default.queue, curr.connect, default.connect.
4437 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004438 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004439 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004440 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004441 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004442 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004443 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004444 }
4445 }
4446
Willy Tarreauf3c69202006-07-09 16:42:34 +02004447 if (curproxy->options & PR_O_SSL3_CHK) {
4448 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4449 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4450 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4451 }
4452
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004453 /* The small pools required for the capture lists */
4454 if (curproxy->nb_req_cap)
4455 curproxy->req_cap_pool = create_pool("ptrcap",
4456 curproxy->nb_req_cap * sizeof(char *),
4457 MEM_F_SHARED);
4458 if (curproxy->nb_rsp_cap)
4459 curproxy->rsp_cap_pool = create_pool("ptrcap",
4460 curproxy->nb_rsp_cap * sizeof(char *),
4461 MEM_F_SHARED);
4462
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004463 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4464 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4465 MEM_F_SHARED);
4466
Willy Tarreau86034312006-12-29 00:10:33 +01004467 /* for backwards compatibility with "listen" instances, if
4468 * fullconn is not set but maxconn is set, then maxconn
4469 * is used.
4470 */
4471 if (!curproxy->fullconn)
4472 curproxy->fullconn = curproxy->maxconn;
4473
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 /* first, we will invert the servers list order */
4475 newsrv = NULL;
4476 while (curproxy->srv) {
4477 struct server *next;
4478
4479 next = curproxy->srv->next;
4480 curproxy->srv->next = newsrv;
4481 newsrv = curproxy->srv;
4482 if (!next)
4483 break;
4484 curproxy->srv = next;
4485 }
4486
Willy Tarreau20697042007-11-15 23:26:18 +01004487 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004488 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004490 /* We have to initialize the server lookup mechanism depending
4491 * on what LB algorithm was choosen.
4492 */
4493
4494 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4495 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4496 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004497 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4498 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4499 init_server_map(curproxy);
4500 } else {
4501 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4502 fwrr_init_server_groups(curproxy);
4503 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004504 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004505
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004506 case BE_LB_KIND_LC:
4507 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004508 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004509 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004510
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004511 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004512 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4513 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4514 chash_init_server_tree(curproxy);
4515 } else {
4516 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4517 init_server_map(curproxy);
4518 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004519 break;
4520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521
4522 if (curproxy->options & PR_O_LOGASAP)
4523 curproxy->to_log &= ~LW_BYTES;
4524
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004525 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4526 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4527 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4528 proxy_type_str(curproxy), curproxy->id);
4529 err_code |= ERR_WARN;
4530 }
4531
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004533 * ensure that we're not cross-dressing a TCP server into HTTP.
4534 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004535 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004536 newsrv = curproxy->srv;
4537 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004538 if (!newsrv->puid) {
4539 /* server ID not set, use automatic numbering with first
4540 * spare entry starting with next_svid.
4541 */
4542 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4543 newsrv->conf.id.key = newsrv->puid = next_id;
4544 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4545 next_id++;
4546 }
4547
Willy Tarreau21d2af32008-02-14 20:25:24 +01004548 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004549 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4550 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004551 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004552 }
4553 newsrv = newsrv->next;
4554 }
4555
4556 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 * If this server supports a maxconn parameter, it needs a dedicated
4558 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004559 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004560 */
4561 newsrv = curproxy->srv;
4562 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004563 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 /* Only 'minconn' was specified, or it was higher than or equal
4565 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4566 * this will avoid further useless expensive computations.
4567 */
4568 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004569 } else if (newsrv->maxconn && !newsrv->minconn) {
4570 /* minconn was not specified, so we set it to maxconn */
4571 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004572 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004573 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4574 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004575 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 }
4577
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004578 if (newsrv->trackit) {
4579 struct proxy *px;
4580 struct server *srv;
4581 char *pname, *sname;
4582
4583 pname = newsrv->trackit;
4584 sname = strrchr(pname, '/');
4585
4586 if (sname)
4587 *sname++ = '\0';
4588 else {
4589 sname = pname;
4590 pname = NULL;
4591 }
4592
4593 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004594 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004595 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004596 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4597 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004598 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004599 cfgerr++;
4600 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004601 }
4602 } else
4603 px = curproxy;
4604
4605 srv = findserver(px, sname);
4606 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004607 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4608 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004609 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004610 cfgerr++;
4611 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004612 }
4613
4614 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004615 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004616 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004617 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004618 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004619 cfgerr++;
4620 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004621 }
4622
4623 if (curproxy != px &&
4624 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004625 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004626 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004627 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004628 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004629 cfgerr++;
4630 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004631 }
4632
4633 newsrv->tracked = srv;
4634 newsrv->tracknext = srv->tracknext;
4635 srv->tracknext = newsrv;
4636
4637 free(newsrv->trackit);
4638 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004639 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 newsrv = newsrv->next;
4641 }
4642
Willy Tarreauc1a21672009-08-16 22:37:44 +02004643 if (curproxy->cap & PR_CAP_FE) {
4644 if (curproxy->tcp_req.inspect_delay ||
4645 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4646 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4647
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004648 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004649 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004650 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004651 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004652
4653 /* both TCP and HTTP must check switching rules */
4654 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4655 }
4656
4657 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004658 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004659 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004660 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004661 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004662
4663 /* If the backend does requires RDP cookie persistence, we have to
4664 * enable the corresponding analyser.
4665 */
4666 if (curproxy->options2 & PR_O2_RDPC_PRST)
4667 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4668 }
4669
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004670 listener = NULL;
4671 while (curproxy->listen) {
4672 struct listener *next;
4673
4674 next = curproxy->listen->next;
4675 curproxy->listen->next = listener;
4676 listener = curproxy->listen;
4677
4678 if (!next)
4679 break;
4680
4681 curproxy->listen = next;
4682 }
4683
Willy Tarreaue6b98942007-10-29 01:09:36 +01004684 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004685 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004686 listener = curproxy->listen;
4687 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004688 if (!listener->luid) {
4689 /* listener ID not set, use automatic numbering with first
4690 * spare entry starting with next_luid.
4691 */
4692 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4693 listener->conf.id.key = listener->luid = next_id;
4694 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4695 next_id++;
4696 }
4697
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004698 /* enable separate counters */
4699 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4700 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4701 if (!listener->name) {
4702 sprintf(trash, "sock-%d", listener->luid);
4703 listener->name = strdup(trash);
4704 }
4705 }
4706
Willy Tarreaue6b98942007-10-29 01:09:36 +01004707 if (curproxy->options & PR_O_TCP_NOLING)
4708 listener->options |= LI_O_NOLINGER;
4709 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004710 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004711 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004712 listener->accept = event_accept;
4713 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004714 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004715 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004716
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004717 /* smart accept mode is automatic in HTTP mode */
4718 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4719 (curproxy->mode == PR_MODE_HTTP &&
4720 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4721 listener->options |= LI_O_NOQUICKACK;
4722
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004723 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004724 listener = listener->next;
4725 }
4726
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 curproxy = curproxy->next;
4728 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004729
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004730 /*
4731 * Recount currently required checks.
4732 */
4733
4734 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4735 int optnum;
4736
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004737 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4738 if (curproxy->options & cfg_opts[optnum].val)
4739 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004740
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004741 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4742 if (curproxy->options2 & cfg_opts2[optnum].val)
4743 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004744 }
4745
Willy Tarreaubb925012009-07-23 13:36:36 +02004746 if (cfgerr > 0)
4747 err_code |= ERR_ALERT | ERR_FATAL;
4748 out:
4749 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750}
4751
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004752/*
4753 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4754 * parsing sessions.
4755 */
4756void cfg_register_keywords(struct cfg_kw_list *kwl)
4757{
4758 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4759}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004761/*
4762 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4763 */
4764void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4765{
4766 LIST_DEL(&kwl->list);
4767 LIST_INIT(&kwl->list);
4768}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769
4770/*
4771 * Local variables:
4772 * c-indent-level: 8
4773 * c-basic-offset: 8
4774 * End:
4775 */