blob: fdaa6062b94980f793a15d2712a8de6bb9893dba [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004 * Copyright 2000-2009 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{
330 if (proxy->nb_reqadd) {
331 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
786
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200787void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788{
789 memset(&defproxy, 0, sizeof(defproxy));
790 defproxy.mode = PR_MODE_TCP;
791 defproxy.state = PR_STNEW;
792 defproxy.maxconn = cfg_maxpconn;
793 defproxy.conn_retries = CONN_RETRIES;
794 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200795
796 LIST_INIT(&defproxy.pendconns);
797 LIST_INIT(&defproxy.acl);
798 LIST_INIT(&defproxy.block_cond);
799 LIST_INIT(&defproxy.mon_fail_cond);
800 LIST_INIT(&defproxy.switching_rules);
801
Willy Tarreau3a70f942008-02-15 11:15:34 +0100802 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803}
804
805/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100806 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200807 * Returns the error code, 0 if OK, or any combination of :
808 * - ERR_ABORT: must abort ASAP
809 * - ERR_FATAL: we can continue parsing but not start the service
810 * - ERR_WARN: a warning has been emitted
811 * - ERR_ALERT: an alert has been emitted
812 * Only the two first ones can stop processing, the two others are just
813 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200815int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200816{
817 static struct proxy *curproxy = NULL;
818 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200819 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100820 int rc;
821 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200822 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823
Willy Tarreau977b8e42006-12-29 14:19:17 +0100824 if (!strcmp(args[0], "listen"))
825 rc = PR_CAP_LISTEN;
826 else if (!strcmp(args[0], "frontend"))
827 rc = PR_CAP_FE | PR_CAP_RS;
828 else if (!strcmp(args[0], "backend"))
829 rc = PR_CAP_BE | PR_CAP_RS;
830 else if (!strcmp(args[0], "ruleset"))
831 rc = PR_CAP_RS;
832 else
833 rc = PR_CAP_NONE;
834
835 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 if (!*args[1]) {
837 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
838 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
839 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200840 err_code |= ERR_ALERT | ERR_ABORT;
841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200842 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200843
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100844 err = invalid_char(args[1]);
845 if (err) {
846 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
847 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200848 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100849 }
850
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200851 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
852 /*
853 * If there are two proxies with the same name only following
854 * combinations are allowed:
855 *
856 * listen backend frontend ruleset
857 * listen - - - -
858 * backend - - OK -
859 * frontend - OK - -
860 * ruleset - - - -
861 */
862
863 if (!strcmp(curproxy->id, args[1]) &&
864 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
865 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200866 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
867 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
868 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200869 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200870 }
871 }
872
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
874 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200875 err_code |= ERR_ALERT | ERR_ABORT;
876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100878
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 curproxy->next = proxy;
880 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200881 curproxy->conf.file = file;
882 curproxy->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200884 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200885 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200886 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100887 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200888 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200889 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890
Willy Tarreauee991362007-05-14 14:37:50 +0200891 /* Timeouts are defined as -1, so we cannot use the zeroed area
892 * as a default value.
893 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100894 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200895
896 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100898 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899
900 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100901 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200902 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200903 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200904 err_code |= ERR_FATAL;
905 goto out;
906 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200907 new = curproxy->listen;
908 while (new != last) {
909 new->conf.file = file;
910 new->conf.line = linenum;
911 new = new->next;
912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 global.maxsock++;
914 }
915
916 /* set default values */
917 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100919 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200920 curproxy->no_options = defproxy.no_options;
921 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100922 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100923 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200924 curproxy->except_net = defproxy.except_net;
925 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200926 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200927 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200929 if (defproxy.fwdfor_hdr_len) {
930 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
931 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
932 }
933
Willy Tarreaub86db342009-11-30 11:50:16 +0100934 if (defproxy.orgto_hdr_len) {
935 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
936 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
937 }
938
Willy Tarreau977b8e42006-12-29 14:19:17 +0100939 if (curproxy->cap & PR_CAP_FE) {
940 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100941 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200942 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100943
944 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200945 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
946 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100947
948 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950
Willy Tarreau977b8e42006-12-29 14:19:17 +0100951 if (curproxy->cap & PR_CAP_BE) {
952 curproxy->fullconn = defproxy.fullconn;
953 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954
Willy Tarreau977b8e42006-12-29 14:19:17 +0100955 if (defproxy.check_req)
956 curproxy->check_req = strdup(defproxy.check_req);
957 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958
Willy Tarreau977b8e42006-12-29 14:19:17 +0100959 if (defproxy.cookie_name)
960 curproxy->cookie_name = strdup(defproxy.cookie_name);
961 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +0100962 if (defproxy.cookie_domain)
963 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +0100964
Emeric Brun647caf12009-06-30 17:57:00 +0200965 if (defproxy.rdp_cookie_name)
966 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
967 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
968
Willy Tarreau01732802007-11-01 22:48:15 +0100969 if (defproxy.url_param_name)
970 curproxy->url_param_name = strdup(defproxy.url_param_name);
971 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100972
Benoitaffb4812009-03-25 13:02:10 +0100973 if (defproxy.hh_name)
974 curproxy->hh_name = strdup(defproxy.hh_name);
975 curproxy->hh_len = defproxy.hh_len;
976 curproxy->hh_match_domain = defproxy.hh_match_domain;
977
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100978 if (defproxy.iface_name)
979 curproxy->iface_name = strdup(defproxy.iface_name);
980 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200983 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100984 if (defproxy.capture_name)
985 curproxy->capture_name = strdup(defproxy.capture_name);
986 curproxy->capture_namelen = defproxy.capture_namelen;
987 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989
Willy Tarreau977b8e42006-12-29 14:19:17 +0100990 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100991 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100992 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100993 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100994 curproxy->uri_auth = defproxy.uri_auth;
995 curproxy->mon_net = defproxy.mon_net;
996 curproxy->mon_mask = defproxy.mon_mask;
997 if (defproxy.monitor_uri)
998 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
999 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001000 if (defproxy.defbe.name)
1001 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001002 }
1003
1004 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001005 curproxy->timeout.connect = defproxy.timeout.connect;
1006 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001007 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001008 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001009 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001010 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001011 curproxy->source_addr = defproxy.source_addr;
1012 }
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 curproxy->mode = defproxy.mode;
1015 curproxy->logfac1 = defproxy.logfac1;
1016 curproxy->logsrv1 = defproxy.logsrv1;
1017 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001018 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 curproxy->logfac2 = defproxy.logfac2;
1020 curproxy->logsrv2 = defproxy.logsrv2;
1021 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001022 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001024 curproxy->conf.used_listener_id = EB_ROOT;
1025 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001026
Willy Tarreau93893792009-07-23 13:19:11 +02001027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 }
1029 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1030 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001031 /* FIXME-20070101: we should do this too at the end of the
1032 * config parsing to free all default values.
1033 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001034 free(defproxy.check_req);
1035 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001036 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001037 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001038 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001039 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001040 free(defproxy.capture_name);
1041 free(defproxy.monitor_uri);
1042 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001043 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001044 free(defproxy.fwdfor_hdr_name);
1045 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001046 free(defproxy.orgto_hdr_name);
1047 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001048
Willy Tarreaua534fea2008-08-03 12:19:50 +02001049 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001050 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001051
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 /* we cannot free uri_auth because it might already be used */
1053 init_default_instance();
1054 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001055 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 }
1058 else if (curproxy == NULL) {
1059 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
1063
Willy Tarreau977b8e42006-12-29 14:19:17 +01001064
1065 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001067 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001068 int cur_arg;
1069
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 if (curproxy == &defproxy) {
1071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001075 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001076 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077
1078 if (strchr(args[1], ':') == NULL) {
1079 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001084
1085 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001086 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto out;
1089 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001090
Willy Tarreau90a570f2009-10-04 20:54:54 +02001091 new_listen = curproxy->listen;
1092 while (new_listen != last_listen) {
1093 new_listen->conf.file = file;
1094 new_listen->conf.line = linenum;
1095 new_listen = new_listen->next;
1096 }
1097
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001098 cur_arg = 2;
1099 while (*(args[cur_arg])) {
1100 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1101#ifdef SO_BINDTODEVICE
1102 struct listener *l;
1103
1104 if (!*args[cur_arg + 1]) {
1105 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001109 }
1110
1111 for (l = curproxy->listen; l != last_listen; l = l->next)
1112 l->interface = strdup(args[cur_arg + 1]);
1113
1114 global.last_checks |= LSTCHK_NETADM;
1115
1116 cur_arg += 2;
1117 continue;
1118#else
1119 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1120 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001123#endif
1124 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001125 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1126#ifdef TCP_MAXSEG
1127 struct listener *l;
1128 int mss;
1129
1130 if (!*args[cur_arg + 1]) {
1131 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1132 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001135 }
1136
1137 mss = str2uic(args[cur_arg + 1]);
1138 if (mss < 1 || mss > 65535) {
1139 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001143 }
1144
1145 for (l = curproxy->listen; l != last_listen; l = l->next)
1146 l->maxseg = mss;
1147
1148 cur_arg += 2;
1149 continue;
1150#else
1151 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1152 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001155#endif
1156 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001157
1158 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1159#ifdef TCP_DEFER_ACCEPT
1160 struct listener *l;
1161
1162 for (l = curproxy->listen; l != last_listen; l = l->next)
1163 l->options |= LI_O_DEF_ACCEPT;
1164
1165 cur_arg ++;
1166 continue;
1167#else
1168 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1169 file, linenum, args[0], args[cur_arg]);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
1172#endif
1173 }
1174
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001175 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001176#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001177 struct listener *l;
1178
1179 for (l = curproxy->listen; l != last_listen; l = l->next)
1180 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001181
1182 cur_arg ++;
1183 continue;
1184#else
1185 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1186 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001189#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001190 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001191
1192 if (!strcmp(args[cur_arg], "name")) {
1193 struct listener *l;
1194
1195 for (l = curproxy->listen; l != last_listen; l = l->next)
1196 l->name = strdup(args[cur_arg + 1]);
1197
1198 cur_arg += 2;
1199 continue;
1200 }
1201
1202 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001203 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001204 struct listener *l;
1205
1206 if (curproxy->listen->next != last_listen) {
1207 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1208 file, linenum, args[cur_arg]);
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 goto out;
1211 }
1212
1213 if (!*args[cur_arg + 1]) {
1214 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1215 file, linenum, args[cur_arg]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218 }
1219
1220 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001221 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001222
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001223 if (curproxy->listen->luid <= 0) {
1224 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001225 file, linenum);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001230 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1231 if (node) {
1232 l = container_of(node, struct listener, conf.id);
1233 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1234 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1239
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001240 cur_arg += 2;
1241 continue;
1242 }
1243
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001244 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 +01001245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001246 err_code |= ERR_ALERT | ERR_FATAL;
1247 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 }
1252 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1253 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1254 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1255 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001259 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001260 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001261
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 /* flush useless bits */
1263 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001265 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001266 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001267 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001268 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001269
Willy Tarreau1c47f852006-07-09 08:22:27 +02001270 if (!*args[1]) {
1271 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1272 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001275 }
1276
Willy Tarreaua534fea2008-08-03 12:19:50 +02001277 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001278 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001279 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001280 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001281 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1282
Willy Tarreau93893792009-07-23 13:19:11 +02001283 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1286 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1287 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1288 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1289 else {
1290 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 }
1294 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001295 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001296 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001297
1298 if (curproxy == &defproxy) {
1299 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1300 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001303 }
1304
1305 if (!*args[1]) {
1306 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001310 }
1311
1312 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001313 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001314
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001315 if (curproxy->uuid <= 0) {
1316 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001317 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001320 }
1321
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001322 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1323 if (node) {
1324 struct proxy *target = container_of(node, struct proxy, conf.id);
1325 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1326 file, linenum, proxy_type_str(curproxy), curproxy->id,
1327 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001332 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001333 else if (!strcmp(args[0], "description")) {
1334 int i, len=0;
1335 char *d;
1336
1337 if (!*args[1]) {
1338 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1339 file, linenum, args[0]);
1340 return -1;
1341 }
1342
1343 for(i=1; *args[i]; i++)
1344 len += strlen(args[i])+1;
1345
1346 d = (char *)calloc(1, len);
1347 curproxy->desc = d;
1348
1349 d += sprintf(d, "%s", args[1]);
1350 for(i=2; *args[i]; i++)
1351 d += sprintf(d, " %s", args[i]);
1352
1353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1355 curproxy->state = PR_STSTOPPED;
1356 }
1357 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1358 curproxy->state = PR_STNEW;
1359 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001360 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1361 int cur_arg = 1;
1362 unsigned int set = 0;
1363
1364 while (*args[cur_arg]) {
1365 int u;
1366 if (strcmp(args[cur_arg], "all") == 0) {
1367 set = 0;
1368 break;
1369 }
1370 else if (strcmp(args[cur_arg], "odd") == 0) {
1371 set |= 0x55555555;
1372 }
1373 else if (strcmp(args[cur_arg], "even") == 0) {
1374 set |= 0xAAAAAAAA;
1375 }
1376 else {
1377 u = str2uic(args[cur_arg]);
1378 if (u < 1 || u > 32) {
1379 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001383 }
1384 if (u > global.nbproc) {
1385 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001387 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001388 }
1389 set |= 1 << (u - 1);
1390 }
1391 cur_arg++;
1392 }
1393 curproxy->bind_proc = set;
1394 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001395 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001396 if (curproxy == &defproxy) {
1397 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001400 }
1401
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001402 err = invalid_char(args[1]);
1403 if (err) {
1404 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1405 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001407 }
1408
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001409 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1410 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1411 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001414 }
1415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1417 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
Willy Tarreau977b8e42006-12-29 14:19:17 +01001419 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001420 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 if (*(args[1]) == 0) {
1423 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1424 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001425 err_code |= ERR_ALERT | ERR_FATAL;
1426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001428
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001429 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001430 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 curproxy->cookie_name = strdup(args[1]);
1432 curproxy->cookie_len = strlen(curproxy->cookie_name);
1433
1434 cur_arg = 2;
1435 while (*(args[cur_arg])) {
1436 if (!strcmp(args[cur_arg], "rewrite")) {
1437 curproxy->options |= PR_O_COOK_RW;
1438 }
1439 else if (!strcmp(args[cur_arg], "indirect")) {
1440 curproxy->options |= PR_O_COOK_IND;
1441 }
1442 else if (!strcmp(args[cur_arg], "insert")) {
1443 curproxy->options |= PR_O_COOK_INS;
1444 }
1445 else if (!strcmp(args[cur_arg], "nocache")) {
1446 curproxy->options |= PR_O_COOK_NOC;
1447 }
1448 else if (!strcmp(args[cur_arg], "postonly")) {
1449 curproxy->options |= PR_O_COOK_POST;
1450 }
1451 else if (!strcmp(args[cur_arg], "prefix")) {
1452 curproxy->options |= PR_O_COOK_PFX;
1453 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001454 else if (!strcmp(args[cur_arg], "domain")) {
1455 if (!*args[cur_arg + 1]) {
1456 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1457 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001458 err_code |= ERR_ALERT | ERR_FATAL;
1459 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001460 }
1461
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001462 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001463 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001464 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1465 " dots nor does not start with a dot."
1466 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001467 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001468 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001469 }
1470
1471 err = invalid_domainchar(args[cur_arg + 1]);
1472 if (err) {
1473 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1474 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001477 }
1478
Willy Tarreau68a897b2009-12-03 23:28:34 +01001479 if (!curproxy->cookie_domain) {
1480 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1481 } else {
1482 /* one domain was already specified, add another one by
1483 * building the string which will be returned along with
1484 * the cookie.
1485 */
1486 char *new_ptr;
1487 int new_len = strlen(curproxy->cookie_domain) +
1488 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1489 new_ptr = malloc(new_len);
1490 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1491 free(curproxy->cookie_domain);
1492 curproxy->cookie_domain = new_ptr;
1493 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001494 cur_arg++;
1495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001497 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 }
1502 cur_arg++;
1503 }
1504 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1505 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1506 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508 }
1509
1510 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1511 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1512 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001513 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514 }
1515 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001516 else if (!strcmp(args[0], "persist")) { /* persist */
1517 if (*(args[1]) == 0) {
1518 Alert("parsing [%s:%d] : missing persist method.\n",
1519 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001522 }
1523
1524 if (!strncmp(args[1], "rdp-cookie", 10)) {
1525 curproxy->options2 |= PR_O2_RDPC_PRST;
1526
1527 if (*(args[1] + 10 ) == '(') { /* cookie name */
1528 const char *beg, *end;
1529
1530 beg = args[1] + 11;
1531 end = strchr(beg, ')');
1532
1533 if (!end || end == beg) {
1534 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1535 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001538 }
1539
1540 free(curproxy->rdp_cookie_name);
1541 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1542 curproxy->rdp_cookie_len = end-beg;
1543 }
1544 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1545 free(curproxy->rdp_cookie_name);
1546 curproxy->rdp_cookie_name = strdup("msts");
1547 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1548 }
1549 else { /* syntax */
1550 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1551 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001552 err_code |= ERR_ALERT | ERR_FATAL;
1553 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001554 }
1555 }
1556 else {
1557 Alert("parsing [%s:%d] : unknown persist method.\n",
1558 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001559 err_code |= ERR_ALERT | ERR_FATAL;
1560 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001561 }
1562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001564 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001567 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001570 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001572 err_code |= ERR_ALERT | ERR_FATAL;
1573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 }
1575 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001576 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 curproxy->appsession_name = strdup(args[1]);
1578 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1579 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001580 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1581 if (err) {
1582 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1583 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001586 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001587 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001588
Willy Tarreau51041c72007-09-09 21:56:53 +02001589 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1590 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001591 err_code |= ERR_ALERT | ERR_ABORT;
1592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001594
1595 cur_arg = 6;
1596 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001597 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1598 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001599 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001600 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001601 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001602 } else if (!strcmp(args[cur_arg], "prefix")) {
1603 curproxy->options2 |= PR_O2_AS_PFX;
1604 } else if (!strcmp(args[cur_arg], "mode")) {
1605 if (!*args[cur_arg + 1]) {
1606 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1607 file, linenum, args[0], args[cur_arg]);
1608 err_code |= ERR_ALERT | ERR_FATAL;
1609 goto out;
1610 }
1611
1612 cur_arg++;
1613 if (!strcmp(args[cur_arg], "query-string")) {
1614 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1615 curproxy->options2 |= PR_O2_AS_M_QS;
1616 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1617 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1618 curproxy->options2 |= PR_O2_AS_M_PP;
1619 } else {
1620 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001625 cur_arg++;
1626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 } /* Url App Session */
1628 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001629 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001630 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 if (*(args[4]) == 0) {
1634 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001639 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 curproxy->capture_name = strdup(args[2]);
1641 curproxy->capture_namelen = strlen(curproxy->capture_name);
1642 curproxy->capture_len = atol(args[4]);
1643 if (curproxy->capture_len >= CAPTURE_LEN) {
1644 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1645 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001646 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 curproxy->capture_len = CAPTURE_LEN - 1;
1648 }
1649 curproxy->to_log |= LW_COOKIE;
1650 }
1651 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1652 struct cap_hdr *hdr;
1653
1654 if (curproxy == &defproxy) {
1655 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 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 }
1659
1660 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1661 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1662 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
1666
1667 hdr = calloc(sizeof(struct cap_hdr), 1);
1668 hdr->next = curproxy->req_cap;
1669 hdr->name = strdup(args[3]);
1670 hdr->namelen = strlen(args[3]);
1671 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001672 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 hdr->index = curproxy->nb_req_cap++;
1674 curproxy->req_cap = hdr;
1675 curproxy->to_log |= LW_REQHDR;
1676 }
1677 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1678 struct cap_hdr *hdr;
1679
1680 if (curproxy == &defproxy) {
1681 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 +02001682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 }
1685
1686 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1687 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1688 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 }
1692 hdr = calloc(sizeof(struct cap_hdr), 1);
1693 hdr->next = curproxy->rsp_cap;
1694 hdr->name = strdup(args[3]);
1695 hdr->namelen = strlen(args[3]);
1696 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001697 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 hdr->index = curproxy->nb_rsp_cap++;
1699 curproxy->rsp_cap = hdr;
1700 curproxy->to_log |= LW_RSPHDR;
1701 }
1702 else {
1703 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1704 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
1706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 }
1708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001712
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 if (*(args[1]) == 0) {
1714 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 }
1719 curproxy->conn_retries = atol(args[1]);
1720 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001721 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1722 int pol = ACL_COND_NONE;
1723 struct acl_cond *cond;
1724
Willy Tarreaub099aca2008-10-12 17:26:37 +02001725 if (curproxy == &defproxy) {
1726 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001729 }
1730
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001731 if (!strcmp(args[1], "if"))
1732 pol = ACL_COND_IF;
1733 else if (!strcmp(args[1], "unless"))
1734 pol = ACL_COND_UNLESS;
1735
1736 if (pol == ACL_COND_NONE) {
1737 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1738 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001739 err_code |= ERR_ALERT | ERR_FATAL;
1740 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001741 }
1742
1743 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1744 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1745 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001746 err_code |= ERR_ALERT | ERR_FATAL;
1747 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001748 }
Willy Tarreau88922352009-10-04 22:02:50 +02001749 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001750 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001751 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001752 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001753 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001754 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001755 else if (!strcmp(args[0], "redirect")) {
1756 int pol = ACL_COND_NONE;
1757 struct acl_cond *cond;
1758 struct redirect_rule *rule;
1759 int cur_arg;
1760 int type = REDIRECT_TYPE_NONE;
1761 int code = 302;
1762 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001763 char *cookie = NULL;
1764 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001765 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001766
1767 cur_arg = 1;
1768 while (*(args[cur_arg])) {
1769 if (!strcmp(args[cur_arg], "location")) {
1770 if (!*args[cur_arg + 1]) {
1771 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1772 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001775 }
1776
1777 type = REDIRECT_TYPE_LOCATION;
1778 cur_arg++;
1779 destination = args[cur_arg];
1780 }
1781 else if (!strcmp(args[cur_arg], "prefix")) {
1782 if (!*args[cur_arg + 1]) {
1783 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1784 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001787 }
1788
1789 type = REDIRECT_TYPE_PREFIX;
1790 cur_arg++;
1791 destination = args[cur_arg];
1792 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001793 else if (!strcmp(args[cur_arg], "set-cookie")) {
1794 if (!*args[cur_arg + 1]) {
1795 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1796 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001799 }
1800
1801 cur_arg++;
1802 cookie = args[cur_arg];
1803 cookie_set = 1;
1804 }
1805 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1806 if (!*args[cur_arg + 1]) {
1807 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1808 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001811 }
1812
1813 cur_arg++;
1814 cookie = args[cur_arg];
1815 cookie_set = 0;
1816 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001817 else if (!strcmp(args[cur_arg],"code")) {
1818 if (!*args[cur_arg + 1]) {
1819 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1820 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001823 }
1824 cur_arg++;
1825 code = atol(args[cur_arg]);
1826 if (code < 301 || code > 303) {
1827 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1828 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001831 }
1832 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001833 else if (!strcmp(args[cur_arg],"drop-query")) {
1834 flags |= REDIRECT_FLAG_DROP_QS;
1835 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001836 else if (!strcmp(args[cur_arg], "if")) {
1837 pol = ACL_COND_IF;
1838 cur_arg++;
1839 break;
1840 }
1841 else if (!strcmp(args[cur_arg], "unless")) {
1842 pol = ACL_COND_UNLESS;
1843 cur_arg++;
1844 break;
1845 }
1846 else {
1847 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1848 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001851 }
1852 cur_arg++;
1853 }
1854
1855 if (type == REDIRECT_TYPE_NONE) {
1856 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1857 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001860 }
1861
1862 if (pol == ACL_COND_NONE) {
1863 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1864 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001867 }
1868
1869 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001870 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001871 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001872 err_code |= ERR_ALERT | ERR_FATAL;
1873 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001874 }
1875
Willy Tarreau88922352009-10-04 22:02:50 +02001876 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001877 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001878 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001879 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1880 rule->cond = cond;
1881 rule->rdr_str = strdup(destination);
1882 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001883 if (cookie) {
1884 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1885 * a clear consists in appending "; Max-Age=0" at the end.
1886 */
1887 rule->cookie_len = strlen(cookie);
1888 if (cookie_set)
1889 rule->cookie_str = strdup(cookie);
1890 else {
1891 rule->cookie_str = malloc(rule->cookie_len + 12);
1892 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1893 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1894 rule->cookie_len += 11;
1895 }
1896 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001897 rule->type = type;
1898 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001899 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001900 LIST_INIT(&rule->list);
1901 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001902 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001903 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001904 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001905 int pol = ACL_COND_NONE;
1906 struct acl_cond *cond;
1907 struct switching_rule *rule;
1908
Willy Tarreaub099aca2008-10-12 17:26:37 +02001909 if (curproxy == &defproxy) {
1910 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001913 }
1914
Willy Tarreau55ea7572007-06-17 19:56:27 +02001915 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001916 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001917
1918 if (*(args[1]) == 0) {
1919 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001920 err_code |= ERR_ALERT | ERR_FATAL;
1921 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001922 }
1923
1924 if (!strcmp(args[2], "if"))
1925 pol = ACL_COND_IF;
1926 else if (!strcmp(args[2], "unless"))
1927 pol = ACL_COND_UNLESS;
1928
1929 if (pol == ACL_COND_NONE) {
1930 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001934 }
1935
1936 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001937 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001938 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001941 }
1942
Willy Tarreau88922352009-10-04 22:02:50 +02001943 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001944 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001945 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001946 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001947 struct acl *acl;
1948 const char *name;
1949
1950 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1951 name = acl ? acl->name : "(unknown)";
1952 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1953 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001955 }
1956
Willy Tarreau55ea7572007-06-17 19:56:27 +02001957 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1958 rule->cond = cond;
1959 rule->be.name = strdup(args[1]);
1960 LIST_INIT(&rule->list);
1961 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001964 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001966
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1968 curproxy->uri_auth = NULL; /* we must detach from the default config */
1969
1970 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001971 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable', 'hide-version', 'show-node', 'show-desc'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001972 err_code |= ERR_ALERT | ERR_FATAL;
1973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974 } else if (!strcmp(args[1], "uri")) {
1975 if (*(args[2]) == 0) {
1976 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001977 err_code |= ERR_ALERT | ERR_FATAL;
1978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1980 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001981 err_code |= ERR_ALERT | ERR_ABORT;
1982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 }
1984 } else if (!strcmp(args[1], "realm")) {
1985 if (*(args[2]) == 0) {
1986 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_ALERT | ERR_FATAL;
1988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1990 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001991 err_code |= ERR_ALERT | ERR_ABORT;
1992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001994 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001995 unsigned interval;
1996
1997 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1998 if (err) {
1999 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2000 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002003 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2004 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002005 err_code |= ERR_ALERT | ERR_ABORT;
2006 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 } else if (!strcmp(args[1], "auth")) {
2009 if (*(args[2]) == 0) {
2010 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2014 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_ALERT | ERR_ABORT;
2016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 }
2018 } else if (!strcmp(args[1], "scope")) {
2019 if (*(args[2]) == 0) {
2020 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2024 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002025 err_code |= ERR_ALERT | ERR_ABORT;
2026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 }
2028 } else if (!strcmp(args[1], "enable")) {
2029 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2030 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_ABORT;
2032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002034 } else if (!strcmp(args[1], "hide-version")) {
2035 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
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;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002039 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002040 } else if (!strcmp(args[1], "show-node")) {
2041
2042 if (*args[2]) {
2043 int i;
2044 char c;
2045
2046 for (i=0; args[2][i]; i++) {
2047 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002048 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002049 break;
2050 }
2051
2052 if (!i || args[2][i]) {
2053 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2054 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2055 file, linenum, args[0], args[1]);
2056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
2058 }
2059 }
2060
2061 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2062 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2063 err_code |= ERR_ALERT | ERR_ABORT;
2064 goto out;
2065 }
2066 } else if (!strcmp(args[1], "show-desc")) {
2067 char *desc = NULL;
2068
2069 if (*args[2]) {
2070 int i, len=0;
2071 char *d;
2072
2073 for(i=2; *args[i]; i++)
2074 len += strlen(args[i])+1;
2075
2076 desc = d = (char *)calloc(1, len);
2077
2078 d += sprintf(d, "%s", args[2]);
2079 for(i=3; *args[i]; i++)
2080 d += sprintf(d, " %s", args[i]);
2081 }
2082
2083 if (!*args[2] && !global.desc)
2084 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2085 file, linenum, args[1]);
2086 else {
2087 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2088 free(desc);
2089 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2090 err_code |= ERR_ALERT | ERR_ABORT;
2091 goto out;
2092 }
2093 free(desc);
2094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002096 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 }
2101 }
2102 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002103 int optnum;
2104
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002105 if (*(args[1]) == '\0') {
2106 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2107 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002111
2112 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2113 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002114 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2115 err_code |= ERR_WARN;
2116 goto out;
2117 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002118
Willy Tarreau3842f002009-06-14 11:39:52 +02002119 curproxy->no_options &= ~cfg_opts[optnum].val;
2120 curproxy->options &= ~cfg_opts[optnum].val;
2121
2122 switch (kwm) {
2123 case KWM_STD:
2124 curproxy->options |= cfg_opts[optnum].val;
2125 break;
2126 case KWM_NO:
2127 curproxy->no_options |= cfg_opts[optnum].val;
2128 break;
2129 case KWM_DEF: /* already cleared */
2130 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002131 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002132
Willy Tarreau93893792009-07-23 13:19:11 +02002133 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002134 }
2135 }
2136
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002137 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2138 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002139 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2140 err_code |= ERR_WARN;
2141 goto out;
2142 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002143
Willy Tarreau3842f002009-06-14 11:39:52 +02002144 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2145 curproxy->options2 &= ~cfg_opts2[optnum].val;
2146
2147 switch (kwm) {
2148 case KWM_STD:
2149 curproxy->options2 |= cfg_opts2[optnum].val;
2150 break;
2151 case KWM_NO:
2152 curproxy->no_options2 |= cfg_opts2[optnum].val;
2153 break;
2154 case KWM_DEF: /* already cleared */
2155 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002156 }
Willy Tarreau93893792009-07-23 13:19:11 +02002157 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002158 }
2159 }
2160
Willy Tarreau3842f002009-06-14 11:39:52 +02002161 if (kwm != KWM_STD) {
2162 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002163 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002166 }
2167
Emeric Brun3a058f32009-06-30 18:26:00 +02002168 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002169 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002170 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002172 if (*(args[2]) != '\0') {
2173 if (!strcmp(args[2], "clf")) {
2174 curproxy->options2 |= PR_O2_CLFLOG;
2175 } else {
2176 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002179 }
2180 }
2181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 else if (!strcmp(args[1], "tcplog"))
2183 /* generate a detailed TCP log */
2184 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 else if (!strcmp(args[1], "tcpka")) {
2186 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002187 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002189
2190 if (curproxy->cap & PR_CAP_FE)
2191 curproxy->options |= PR_O_TCP_CLI_KA;
2192 if (curproxy->cap & PR_CAP_BE)
2193 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 }
2195 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002196 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_WARN;
2198
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002200 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002201 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002202 curproxy->options &= ~PR_O_SMTP_CHK;
2203 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 if (!*args[2]) { /* no argument */
2205 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2206 curproxy->check_len = strlen(DEF_CHECK_REQ);
2207 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002208 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 curproxy->check_req = (char *)malloc(reqlen);
2210 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2211 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2212 } else { /* more arguments : METHOD URI [HTTP_VER] */
2213 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2214 if (*args[4])
2215 reqlen += strlen(args[4]);
2216 else
2217 reqlen += strlen("HTTP/1.0");
2218
2219 curproxy->check_req = (char *)malloc(reqlen);
2220 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2221 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2222 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002223 }
2224 else if (!strcmp(args[1], "ssl-hello-chk")) {
2225 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002228
Willy Tarreaua534fea2008-08-03 12:19:50 +02002229 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002230 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002231 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002232 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 }
Willy Tarreau23677902007-05-08 23:50:35 +02002234 else if (!strcmp(args[1], "smtpchk")) {
2235 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002236 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002237 curproxy->options &= ~PR_O_HTTP_CHK;
2238 curproxy->options &= ~PR_O_SSL3_CHK;
2239 curproxy->options |= PR_O_SMTP_CHK;
2240
2241 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2242 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2243 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2244 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2245 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2246 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2247 curproxy->check_req = (char *)malloc(reqlen);
2248 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2249 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2250 } else {
2251 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2252 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2253 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2254 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2255 }
2256 }
2257 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002258 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002259 int cur_arg;
2260
2261 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2262 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002263 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002264
2265 curproxy->options |= PR_O_FWDFOR;
2266
2267 free(curproxy->fwdfor_hdr_name);
2268 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2269 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2270
2271 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2272 cur_arg = 2;
2273 while (*(args[cur_arg])) {
2274 if (!strcmp(args[cur_arg], "except")) {
2275 /* suboption except - needs additional argument for it */
2276 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2277 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2278 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002281 }
2282 /* flush useless bits */
2283 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002284 cur_arg += 2;
2285 } else if (!strcmp(args[cur_arg], "header")) {
2286 /* suboption header - needs additional argument for it */
2287 if (*(args[cur_arg+1]) == 0) {
2288 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2289 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002292 }
2293 free(curproxy->fwdfor_hdr_name);
2294 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2295 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2296 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002297 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002298 /* unknown suboption - catchall */
2299 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2300 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002303 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002304 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002305 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002306 else if (!strcmp(args[1], "originalto")) {
2307 int cur_arg;
2308
2309 /* insert x-original-to field, but not for the IP address listed as an except.
2310 * set default options (ie: bitfield, header name, etc)
2311 */
2312
2313 curproxy->options |= PR_O_ORGTO;
2314
2315 free(curproxy->orgto_hdr_name);
2316 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2317 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2318
2319 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2320 cur_arg = 2;
2321 while (*(args[cur_arg])) {
2322 if (!strcmp(args[cur_arg], "except")) {
2323 /* suboption except - needs additional argument for it */
2324 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2325 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2326 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002329 }
2330 /* flush useless bits */
2331 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2332 cur_arg += 2;
2333 } else if (!strcmp(args[cur_arg], "header")) {
2334 /* suboption header - needs additional argument for it */
2335 if (*(args[cur_arg+1]) == 0) {
2336 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2337 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002340 }
2341 free(curproxy->orgto_hdr_name);
2342 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2343 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2344 cur_arg += 2;
2345 } else {
2346 /* unknown suboption - catchall */
2347 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2348 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002351 }
2352 } /* end while loop */
2353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 else {
2355 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 }
Willy Tarreau93893792009-07-23 13:19:11 +02002359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002361 else if (!strcmp(args[0], "default_backend")) {
2362 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002364
2365 if (*(args[1]) == 0) {
2366 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002369 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002370 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002371 curproxy->defbe.name = strdup(args[1]);
2372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002374 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002377 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2378 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 /* enable reconnections to dispatch */
2381 curproxy->options |= PR_O_REDISP;
2382 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002383 else if (!strcmp(args[0], "http-check")) {
2384 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002386
2387 if (strcmp(args[1], "disable-on-404") == 0) {
2388 /* enable a graceful server shutdown on an HTTP 404 response */
2389 curproxy->options |= PR_O_DISABLE404;
2390 }
2391 else {
2392 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002395 }
2396 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002397 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002398 if (curproxy == &defproxy) {
2399 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002402 }
2403
Willy Tarreaub80c2302007-11-30 20:51:32 +01002404 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002406
2407 if (strcmp(args[1], "fail") == 0) {
2408 /* add a condition to fail monitor requests */
2409 int pol = ACL_COND_NONE;
2410 struct acl_cond *cond;
2411
2412 if (!strcmp(args[2], "if"))
2413 pol = ACL_COND_IF;
2414 else if (!strcmp(args[2], "unless"))
2415 pol = ACL_COND_UNLESS;
2416
2417 if (pol == ACL_COND_NONE) {
2418 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2419 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002422 }
2423
2424 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2425 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2426 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002429 }
Willy Tarreau88922352009-10-04 22:02:50 +02002430 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002431 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002432 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002433 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2434 }
2435 else {
2436 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002439 }
2440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441#ifdef TPROXY
2442 else if (!strcmp(args[0], "transparent")) {
2443 /* enable transparent proxy connections */
2444 curproxy->options |= PR_O_TRANSP;
2445 }
2446#endif
2447 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002448 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 if (*(args[1]) == 0) {
2452 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
2456 curproxy->maxconn = atol(args[1]);
2457 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002458 else if (!strcmp(args[0], "backlog")) { /* backlog */
2459 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002460 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002461
2462 if (*(args[1]) == 0) {
2463 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002466 }
2467 curproxy->backlog = atol(args[1]);
2468 }
Willy Tarreau86034312006-12-29 00:10:33 +01002469 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472
Willy Tarreau86034312006-12-29 00:10:33 +01002473 if (*(args[1]) == 0) {
2474 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002477 }
2478 curproxy->fullconn = atol(args[1]);
2479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2481 if (*(args[1]) == 0) {
2482 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002486 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2487 if (err) {
2488 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2489 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002492 }
2493 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 }
2495 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2496 if (curproxy == &defproxy) {
2497 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002501 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002502 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002503
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 if (strchr(args[1], ':') == NULL) {
2505 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 }
2509 curproxy->dispatch_addr = *str2sa(args[1]);
2510 }
2511 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002513 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002514
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002515 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002516 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2517 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002522 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2523 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2524 err_code |= ERR_WARN;
2525
2526 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2527 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2528 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2529 }
2530 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2531 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2532 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2533 }
2534 else {
2535 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
2538 }
2539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 else if (!strcmp(args[0], "server")) { /* server address */
2541 int cur_arg;
2542 char *rport;
2543 char *raddr;
2544 short realport;
2545 int do_check;
2546
2547 if (curproxy == &defproxy) {
2548 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002552 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554
2555 if (!*args[2]) {
2556 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002561
2562 err = invalid_char(args[1]);
2563 if (err) {
2564 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2565 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002568 }
2569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2571 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_ABORT;
2573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575
2576 /* the servers are linked backwards first */
2577 newsrv->next = curproxy->srv;
2578 curproxy->srv = newsrv;
2579 newsrv->proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002580 newsrv->conf.file = file;
2581 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582
2583 LIST_INIT(&newsrv->pendconns);
2584 do_check = 0;
2585 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002586 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 newsrv->id = strdup(args[1]);
2588
2589 /* several ways to check the port component :
2590 * - IP => port=+0, relative
2591 * - IP: => port=+0, relative
2592 * - IP:N => port=N, absolute
2593 * - IP:+N => port=+N, relative
2594 * - IP:-N => port=-N, relative
2595 */
2596 raddr = strdup(args[2]);
2597 rport = strchr(raddr, ':');
2598 if (rport) {
2599 *rport++ = 0;
2600 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002601 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 newsrv->state |= SRV_MAPPORTS;
2603 } else {
2604 realport = 0;
2605 newsrv->state |= SRV_MAPPORTS;
2606 }
2607
2608 newsrv->addr = *str2sa(raddr);
2609 newsrv->addr.sin_port = htons(realport);
2610 free(raddr);
2611
2612 newsrv->curfd = -1; /* no health-check in progress */
2613 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002614 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2615 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 newsrv->rise = DEF_RISETIME;
2617 newsrv->fall = DEF_FALLTIME;
2618 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau975c50b2009-10-10 19:34:06 +02002619 newsrv->uweight = newsrv->iweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002620 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002621 newsrv->slowstart = 0;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002622 newsrv->onerror = DEF_HANA_ONERR;
2623 newsrv->consecutive_errors_limit = DEF_HANA_ERRLIMIT;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002624
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 cur_arg = 3;
2626 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002627 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002628 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002629
2630 if (!*args[cur_arg + 1]) {
2631 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2632 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002633 err_code |= ERR_ALERT | ERR_FATAL;
2634 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002635 }
2636
2637 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002638 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002639
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002640 if (newsrv->puid <= 0) {
2641 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002642 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002645 }
2646
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002647 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2648 if (node) {
2649 struct server *target = container_of(node, struct server, conf.id);
2650 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2651 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
2654 }
2655 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002656 cur_arg += 2;
2657 }
2658 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659 newsrv->cookie = strdup(args[cur_arg + 1]);
2660 newsrv->cklen = strlen(args[cur_arg + 1]);
2661 cur_arg += 2;
2662 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002663 else if (!strcmp(args[cur_arg], "redir")) {
2664 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2665 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2666 cur_arg += 2;
2667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002669 if (!*args[cur_arg + 1]) {
2670 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2671 file, linenum, args[cur_arg]);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002677 if (newsrv->rise <= 0) {
2678 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2679 file, linenum, args[cur_arg]);
2680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
2682 }
2683
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 newsrv->health = newsrv->rise;
2685 cur_arg += 2;
2686 }
2687 else if (!strcmp(args[cur_arg], "fall")) {
2688 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002689
2690 if (!*args[cur_arg + 1]) {
2691 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2692 file, linenum, args[cur_arg]);
2693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
2695 }
2696
2697 if (newsrv->fall <= 0) {
2698 Alert("parsing [%s:%d]: '%s' has to be > 0.\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 cur_arg += 2;
2705 }
2706 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002707 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2708 if (err) {
2709 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2710 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002713 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002714 if (val <= 0) {
2715 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2716 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002719 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002720 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 cur_arg += 2;
2722 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002723 else if (!strcmp(args[cur_arg], "fastinter")) {
2724 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2725 if (err) {
2726 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2727 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002730 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002731 if (val <= 0) {
2732 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2733 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002736 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002737 newsrv->fastinter = val;
2738 cur_arg += 2;
2739 }
2740 else if (!strcmp(args[cur_arg], "downinter")) {
2741 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2742 if (err) {
2743 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2744 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002747 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002748 if (val <= 0) {
2749 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2750 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002753 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002754 newsrv->downinter = val;
2755 cur_arg += 2;
2756 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002757 else if (!strcmp(args[cur_arg], "addr")) {
2758 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002759 cur_arg += 2;
2760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 else if (!strcmp(args[cur_arg], "port")) {
2762 newsrv->check_port = atol(args[cur_arg + 1]);
2763 cur_arg += 2;
2764 }
2765 else if (!strcmp(args[cur_arg], "backup")) {
2766 newsrv->state |= SRV_BACKUP;
2767 cur_arg ++;
2768 }
2769 else if (!strcmp(args[cur_arg], "weight")) {
2770 int w;
2771 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002772 if (w < 0 || w > 256) {
2773 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002778 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 cur_arg += 2;
2780 }
2781 else if (!strcmp(args[cur_arg], "minconn")) {
2782 newsrv->minconn = atol(args[cur_arg + 1]);
2783 cur_arg += 2;
2784 }
2785 else if (!strcmp(args[cur_arg], "maxconn")) {
2786 newsrv->maxconn = atol(args[cur_arg + 1]);
2787 cur_arg += 2;
2788 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002789 else if (!strcmp(args[cur_arg], "maxqueue")) {
2790 newsrv->maxqueue = atol(args[cur_arg + 1]);
2791 cur_arg += 2;
2792 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002793 else if (!strcmp(args[cur_arg], "slowstart")) {
2794 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002795 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002796 if (err) {
2797 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2798 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002801 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002802 if (val <= 0) {
2803 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2804 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002807 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002808 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002809 cur_arg += 2;
2810 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002811 else if (!strcmp(args[cur_arg], "track")) {
2812
2813 if (!*args[cur_arg + 1]) {
2814 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2815 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002818 }
2819
2820 newsrv->trackit = strdup(args[cur_arg + 1]);
2821
2822 cur_arg += 2;
2823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 else if (!strcmp(args[cur_arg], "check")) {
2825 global.maxsock++;
2826 do_check = 1;
2827 cur_arg += 1;
2828 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002829 else if (!strcmp(args[cur_arg], "observe")) {
2830 if (!strcmp(args[cur_arg + 1], "none"))
2831 newsrv->observe = HANA_OBS_NONE;
2832 else if (!strcmp(args[cur_arg + 1], "layer4"))
2833 newsrv->observe = HANA_OBS_LAYER4;
2834 else if (!strcmp(args[cur_arg + 1], "layer7")) {
2835 if (curproxy->mode != PR_MODE_HTTP) {
2836 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
2837 file, linenum, args[cur_arg + 1]);
2838 err_code |= ERR_ALERT;
2839 }
2840 newsrv->observe = HANA_OBS_LAYER7;
2841 }
2842 else {
2843 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
2844 "'l4events', 'http-responses' but get '%s'\n",
2845 file, linenum, args[cur_arg], args[cur_arg + 1]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849
2850 cur_arg += 2;
2851 }
2852 else if (!strcmp(args[cur_arg], "on-error")) {
2853 if (!strcmp(args[cur_arg + 1], "fastinter"))
2854 newsrv->onerror = HANA_ONERR_FASTINTER;
2855 else if (!strcmp(args[cur_arg + 1], "fail-check"))
2856 newsrv->onerror = HANA_ONERR_FAILCHK;
2857 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
2858 newsrv->onerror = HANA_ONERR_SUDDTH;
2859 else if (!strcmp(args[cur_arg + 1], "mark-down"))
2860 newsrv->onerror = HANA_ONERR_MARKDWN;
2861 else {
2862 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
2863 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
2864 file, linenum, args[cur_arg], args[cur_arg + 1]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867 }
2868
2869 cur_arg += 2;
2870 }
2871 else if (!strcmp(args[cur_arg], "error-limit")) {
2872 if (!*args[cur_arg + 1]) {
2873 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2874 file, linenum, args[cur_arg]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
2878
2879 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
2880
2881 if (newsrv->consecutive_errors_limit <= 0) {
2882 Alert("parsing [%s:%d]: %s has to be > 0.\n",
2883 file, linenum, args[cur_arg]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002889 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002891#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002892 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002893 file, linenum, "source", "usesrc");
2894#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002895 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002897#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 }
2901 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002902 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2903
2904 if (port_low != port_high) {
2905 int i;
2906 if (port_low <= 0 || port_low > 65535 ||
2907 port_high <= 0 || port_high > 65535 ||
2908 port_low > port_high) {
2909 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2910 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002913 }
2914 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2915 for (i = 0; i < newsrv->sport_range->size; i++)
2916 newsrv->sport_range->ports[i] = port_low + i;
2917 }
2918
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002920 while (*(args[cur_arg])) {
2921 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002922#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2923#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002924 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2925 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2926 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002929 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002930#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002931 if (!*args[cur_arg + 1]) {
2932 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2933 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002936 }
2937 if (!strcmp(args[cur_arg + 1], "client")) {
2938 newsrv->state |= SRV_TPROXY_CLI;
2939 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2940 newsrv->state |= SRV_TPROXY_CIP;
2941 } else {
2942 newsrv->state |= SRV_TPROXY_ADDR;
2943 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2944 }
2945 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002946#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002947 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002948#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002949 cur_arg += 2;
2950 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002951#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002952 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002953 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002956#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2957 } /* "usesrc" */
2958
2959 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2960#ifdef SO_BINDTODEVICE
2961 if (!*args[cur_arg + 1]) {
2962 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2963 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002966 }
2967 if (newsrv->iface_name)
2968 free(newsrv->iface_name);
2969
2970 newsrv->iface_name = strdup(args[cur_arg + 1]);
2971 newsrv->iface_len = strlen(newsrv->iface_name);
2972 global.last_checks |= LSTCHK_NETADM;
2973#else
2974 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2975 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002978#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002979 cur_arg += 2;
2980 continue;
2981 }
2982 /* this keyword in not an option of "source" */
2983 break;
2984 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002986 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2987 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2988 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002993 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 }
2998 }
2999
3000 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003001 if (newsrv->trackit) {
3002 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3003 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003006 }
3007
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003008 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3009 newsrv->check_port = newsrv->check_addr.sin_port;
3010
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3012 newsrv->check_port = realport; /* by default */
3013 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003014 /* not yet valid, because no port was set on
3015 * the server either. We'll check if we have
3016 * a known port on the first listener.
3017 */
3018 struct listener *l;
3019 l = curproxy->listen;
3020 if (l) {
3021 int port;
3022 port = (l->addr.ss_family == AF_INET6)
3023 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3024 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3025 newsrv->check_port = port;
3026 }
3027 }
3028 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3030 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003034
3035 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 newsrv->state |= SRV_CHECKED;
3037 }
3038
3039 if (newsrv->state & SRV_BACKUP)
3040 curproxy->srv_bck++;
3041 else
3042 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003043
3044 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 }
3046 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003047 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 int facility;
3049
3050 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3051 curproxy->logfac1 = global.logfac1;
3052 curproxy->logsrv1 = global.logsrv1;
3053 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003054 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 curproxy->logfac2 = global.logfac2;
3056 curproxy->logsrv2 = global.logsrv2;
3057 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003058 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 }
3060 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003061 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062
3063 facility = get_log_facility(args[2]);
3064 if (facility < 0) {
3065 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3066 exit(1);
3067 }
3068
3069 level = 7; /* max syslog level = debug */
3070 if (*(args[3])) {
3071 level = get_log_level(args[3]);
3072 if (level < 0) {
3073 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3074 exit(1);
3075 }
3076 }
3077
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003078 minlvl = 0; /* limit syslog level to this level (emerg) */
3079 if (*(args[4])) {
3080 minlvl = get_log_level(args[4]);
3081 if (level < 0) {
3082 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3083 exit(1);
3084 }
3085 }
3086
Robert Tsai81ae1952007-12-05 10:47:29 +01003087 if (args[1][0] == '/') {
3088 logsrv.u.addr.sa_family = AF_UNIX;
3089 logsrv.u.un = *str2sun(args[1]);
3090 } else {
3091 logsrv.u.addr.sa_family = AF_INET;
3092 logsrv.u.in = *str2sa(args[1]);
3093 if (!logsrv.u.in.sin_port) {
3094 logsrv.u.in.sin_port =
3095 htons(SYSLOG_PORT);
3096 }
3097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098
3099 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003100 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 curproxy->logfac1 = facility;
3102 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003103 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 }
3105 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003106 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 curproxy->logfac2 = facility;
3108 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003109 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 }
3111 else {
3112 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 }
3116 }
3117 else {
3118 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3119 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 }
3123 }
3124 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003125 int cur_arg;
3126
Willy Tarreau977b8e42006-12-29 14:19:17 +01003127 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003129
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003131 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3132 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003136
3137 /* we must first clear any optional default setting */
3138 curproxy->options &= ~PR_O_TPXY_MASK;
3139 free(curproxy->iface_name);
3140 curproxy->iface_name = NULL;
3141 curproxy->iface_len = 0;
3142
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 curproxy->source_addr = *str2sa(args[1]);
3144 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003145
3146 cur_arg = 2;
3147 while (*(args[cur_arg])) {
3148 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003149#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3150#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003151 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3152 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3153 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003156 }
3157#endif
3158 if (!*args[cur_arg + 1]) {
3159 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3160 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003163 }
3164
3165 if (!strcmp(args[cur_arg + 1], "client")) {
3166 curproxy->options |= PR_O_TPXY_CLI;
3167 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3168 curproxy->options |= PR_O_TPXY_CIP;
3169 } else {
3170 curproxy->options |= PR_O_TPXY_ADDR;
3171 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3172 }
3173 global.last_checks |= LSTCHK_NETADM;
3174#if !defined(CONFIG_HAP_LINUX_TPROXY)
3175 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003176#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003177#else /* no TPROXY support */
3178 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003179 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003182#endif
3183 cur_arg += 2;
3184 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003185 }
3186
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003187 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3188#ifdef SO_BINDTODEVICE
3189 if (!*args[cur_arg + 1]) {
3190 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3191 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003194 }
3195 if (curproxy->iface_name)
3196 free(curproxy->iface_name);
3197
3198 curproxy->iface_name = strdup(args[cur_arg + 1]);
3199 curproxy->iface_len = strlen(curproxy->iface_name);
3200 global.last_checks |= LSTCHK_NETADM;
3201#else
3202 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3203 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003206#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003207 cur_arg += 2;
3208 continue;
3209 }
3210 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3211 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003216 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3217 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3218 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3223 regex_t *preg;
3224 if (curproxy == &defproxy) {
3225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003229 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003231
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 if (*(args[1]) == 0 || *(args[2]) == 0) {
3233 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 }
3238
3239 preg = calloc(1, sizeof(regex_t));
3240 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3241 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
3245
3246 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3247 if (err) {
3248 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3249 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003252 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 }
3254 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3255 regex_t *preg;
3256 if (curproxy == &defproxy) {
3257 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003261 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003263
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 if (*(args[1]) == 0) {
3265 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 }
3269
3270 preg = calloc(1, sizeof(regex_t));
3271 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3272 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 }
3276
3277 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003278 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 }
3280 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3281 regex_t *preg;
3282 if (curproxy == &defproxy) {
3283 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003287 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003289
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 if (*(args[1]) == 0) {
3291 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003292 err_code |= ERR_ALERT | ERR_FATAL;
3293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
3295
3296 preg = calloc(1, sizeof(regex_t));
3297 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3298 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
3302
3303 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003304 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
3306 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3307 regex_t *preg;
3308 if (curproxy == &defproxy) {
3309 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003313 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003315
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 if (*(args[1]) == 0) {
3317 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
3321
3322 preg = calloc(1, sizeof(regex_t));
3323 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3324 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328
3329 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003330 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 }
3332 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3333 regex_t *preg;
3334 if (curproxy == &defproxy) {
3335 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003339 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003341
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 if (*(args[1]) == 0) {
3343 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 }
3347
3348 preg = calloc(1, sizeof(regex_t));
3349 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3350 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
3354
3355 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003356 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003358 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3359 regex_t *preg;
3360 if (curproxy == &defproxy) {
3361 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003364 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003365 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003367
Willy Tarreaub8750a82006-09-03 09:56:00 +02003368 if (*(args[1]) == 0) {
3369 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003372 }
3373
3374 preg = calloc(1, sizeof(regex_t));
3375 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3376 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003379 }
3380
3381 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003382 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003383 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003384 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3385 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003386 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003387 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003388 err_code |= ERR_ALERT | ERR_FATAL;
3389 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003390 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003391 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003393
Willy Tarreau977b8e42006-12-29 14:19:17 +01003394 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003395 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3396 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003399 }
3400
3401 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003402 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003403 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003404 err_code |= ERR_ALERT | ERR_FATAL;
3405 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003406 }
3407
3408 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003409 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003410 }
3411 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3412 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003413 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003414 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003417 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003418 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003420
Willy Tarreau977b8e42006-12-29 14:19:17 +01003421 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003422 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3423 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003426 }
3427
3428 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003429 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003430 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003433 }
3434
3435 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003436 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3439 regex_t *preg;
3440 if (curproxy == &defproxy) {
3441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003445 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003446 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003447
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 if (*(args[1]) == 0 || *(args[2]) == 0) {
3449 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003453 }
3454
3455 preg = calloc(1, sizeof(regex_t));
3456 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3457 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003460 }
3461
3462 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3463 if (err) {
3464 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3465 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003469 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 }
3471 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3472 regex_t *preg;
3473 if (curproxy == &defproxy) {
3474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003477 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003478 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003479 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003480
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 if (*(args[1]) == 0) {
3482 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003485 }
3486
3487 preg = calloc(1, sizeof(regex_t));
3488 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3489 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 }
3493
3494 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003495 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 }
3497 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3498 regex_t *preg;
3499 if (curproxy == &defproxy) {
3500 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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 Tarreau977b8e42006-12-29 14:19:17 +01003504 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003506
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 if (*(args[1]) == 0) {
3508 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 }
3512
3513 preg = calloc(1, sizeof(regex_t));
3514 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3515 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519
3520 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003521 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 }
3523 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3524 regex_t *preg;
3525 if (curproxy == &defproxy) {
3526 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003530 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003532
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 if (*(args[1]) == 0) {
3534 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 }
3538
3539 preg = calloc(1, sizeof(regex_t));
3540 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3541 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
3545
3546 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003547 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 }
3549 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3550 regex_t *preg;
3551 if (curproxy == &defproxy) {
3552 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003556 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003558
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 if (*(args[1]) == 0) {
3560 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 }
3564
3565 preg = calloc(1, sizeof(regex_t));
3566 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3567 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 }
3571
3572 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003573 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003575 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3576 regex_t *preg;
3577 if (curproxy == &defproxy) {
3578 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003581 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003582 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003584
Willy Tarreaub8750a82006-09-03 09:56:00 +02003585 if (*(args[1]) == 0) {
3586 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003589 }
3590
3591 preg = calloc(1, sizeof(regex_t));
3592 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3593 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003596 }
3597
3598 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003599 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3602 if (curproxy == &defproxy) {
3603 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003607 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003608 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609
3610 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3611 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 }
3615
3616 if (*(args[1]) == 0) {
3617 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003620 }
3621
3622 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003623 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 }
3625 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3626 regex_t *preg;
3627
3628 if (*(args[1]) == 0 || *(args[2]) == 0) {
3629 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003634 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003636
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 preg = calloc(1, sizeof(regex_t));
3638 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3639 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
3643
3644 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3645 if (err) {
3646 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3647 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003651 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
3653 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3654 regex_t *preg;
3655 if (curproxy == &defproxy) {
3656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003660 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003662
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 if (*(args[1]) == 0) {
3664 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 }
3668
3669 preg = calloc(1, sizeof(regex_t));
3670 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3671 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003674 }
3675
3676 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3677 if (err) {
3678 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3679 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
3683 }
3684 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3685 regex_t *preg;
3686 if (curproxy == &defproxy) {
3687 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003691 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003693
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 if (*(args[1]) == 0) {
3695 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 }
3699
3700 preg = calloc(1, sizeof(regex_t));
3701 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3702 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
3706
3707 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3708 if (err) {
3709 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3710 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003713 }
3714 }
3715 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3716 regex_t *preg;
3717 if (curproxy == &defproxy) {
3718 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003722 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003723 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724
3725 if (*(args[1]) == 0 || *(args[2]) == 0) {
3726 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3727 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 }
3731
3732 preg = calloc(1, sizeof(regex_t));
3733 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3734 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 }
3738
3739 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3740 if (err) {
3741 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3742 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 }
3746 }
3747 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3748 regex_t *preg;
3749 if (curproxy == &defproxy) {
3750 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003753 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003754 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003756
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 if (*(args[1]) == 0) {
3758 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 }
3762
3763 preg = calloc(1, sizeof(regex_t));
3764 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3765 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 }
3769
3770 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3771 if (err) {
3772 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3773 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
3777 }
3778 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3779 regex_t *preg;
3780 if (curproxy == &defproxy) {
3781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003785 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003787
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 if (*(args[1]) == 0) {
3789 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 }
3793
3794 preg = calloc(1, sizeof(regex_t));
3795 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3796 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 }
3800
3801 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3802 if (err) {
3803 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3804 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 }
3808 }
3809 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3810 if (curproxy == &defproxy) {
3811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003815 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817
3818 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3819 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
3823
3824 if (*(args[1]) == 0) {
3825 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 }
3829
3830 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3831 }
3832 else if (!strcmp(args[0], "errorloc") ||
3833 !strcmp(args[0], "errorloc302") ||
3834 !strcmp(args[0], "errorloc303")) { /* error location */
3835 int errnum, errlen;
3836 char *err;
3837
Willy Tarreau977b8e42006-12-29 14:19:17 +01003838 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003840
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003842 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 }
3846
3847 errnum = atol(args[1]);
3848 if (!strcmp(args[0], "errorloc303")) {
3849 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3850 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3851 } else {
3852 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3853 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3854 }
3855
Willy Tarreau0f772532006-12-23 20:51:41 +01003856 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3857 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003858 chunk_destroy(&curproxy->errmsg[rc]);
3859 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003860 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003863
3864 if (rc >= HTTP_ERR_SIZE) {
3865 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3866 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 free(err);
3868 }
3869 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003870 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3871 int errnum, errlen, fd;
3872 char *err;
3873 struct stat stat;
3874
3875 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003877
3878 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003879 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003882 }
3883
3884 fd = open(args[2], O_RDONLY);
3885 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3886 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3887 file, linenum, args[2], args[1]);
3888 if (fd >= 0)
3889 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003892 }
3893
Willy Tarreau27a674e2009-08-17 07:23:33 +02003894 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003895 errlen = stat.st_size;
3896 } else {
3897 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003898 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003900 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003901 }
3902
3903 err = malloc(errlen); /* malloc() must succeed during parsing */
3904 errnum = read(fd, err, errlen);
3905 if (errnum != errlen) {
3906 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3907 file, linenum, args[2], args[1]);
3908 close(fd);
3909 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003912 }
3913 close(fd);
3914
3915 errnum = atol(args[1]);
3916 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3917 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003918 chunk_destroy(&curproxy->errmsg[rc]);
3919 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003920 break;
3921 }
3922 }
3923
3924 if (rc >= HTTP_ERR_SIZE) {
3925 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3926 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003928 free(err);
3929 }
3930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003932 struct cfg_kw_list *kwl;
3933 int index;
3934
3935 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3936 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3937 if (kwl->kw[index].section != CFG_LISTEN)
3938 continue;
3939 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3940 /* prepare error message just in case */
3941 snprintf(trash, sizeof(trash),
3942 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003943 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3944 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003945 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003948 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003949 else if (rc > 0) {
3950 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_WARN;
3952 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003953 }
Willy Tarreau93893792009-07-23 13:19:11 +02003954 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003955 }
3956 }
3957 }
3958
Willy Tarreau6daf3432008-01-22 16:44:08 +01003959 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 }
Willy Tarreau93893792009-07-23 13:19:11 +02003963 out:
3964 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965}
3966
3967
3968/*
3969 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003970 * Returns the error code, 0 if OK, or any combination of :
3971 * - ERR_ABORT: must abort ASAP
3972 * - ERR_FATAL: we can continue parsing but not start the service
3973 * - ERR_WARN: a warning has been emitted
3974 * - ERR_ALERT: an alert has been emitted
3975 * Only the two first ones can stop processing, the two others are just
3976 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003978int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003980 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 FILE *f;
3982 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003984 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 if ((f=fopen(file,"r")) == NULL)
3987 return -1;
3988
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003989 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003990 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003991 char *end;
3992 char *args[MAX_LINE_ARGS + 1];
3993 char *line = thisline;
3994
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 linenum++;
3996
3997 end = line + strlen(line);
3998
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003999 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4000 /* Check if we reached the limit and the last char is not \n.
4001 * Watch out for the last line without the terminating '\n'!
4002 */
4003 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004004 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004006 }
4007
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004009 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 line++;
4011
4012 arg = 0;
4013 args[arg] = line;
4014
4015 while (*line && arg < MAX_LINE_ARGS) {
4016 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4017 * C equivalent value. Other combinations left unchanged (eg: \1).
4018 */
4019 if (*line == '\\') {
4020 int skip = 0;
4021 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4022 *line = line[1];
4023 skip = 1;
4024 }
4025 else if (line[1] == 'r') {
4026 *line = '\r';
4027 skip = 1;
4028 }
4029 else if (line[1] == 'n') {
4030 *line = '\n';
4031 skip = 1;
4032 }
4033 else if (line[1] == 't') {
4034 *line = '\t';
4035 skip = 1;
4036 }
4037 else if (line[1] == 'x') {
4038 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
4039 unsigned char hex1, hex2;
4040 hex1 = toupper(line[2]) - '0';
4041 hex2 = toupper(line[3]) - '0';
4042 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4043 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4044 *line = (hex1<<4) + hex2;
4045 skip = 3;
4046 }
4047 else {
4048 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004049 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 }
4051 }
4052 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004053 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 end -= skip;
4055 }
4056 line++;
4057 }
4058 else if (*line == '#' || *line == '\n' || *line == '\r') {
4059 /* end of string, end of loop */
4060 *line = 0;
4061 break;
4062 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004063 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004065 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004066 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 line++;
4068 args[++arg] = line;
4069 }
4070 else {
4071 line++;
4072 }
4073 }
4074
4075 /* empty line */
4076 if (!**args)
4077 continue;
4078
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004079 if (*line) {
4080 /* we had to stop due to too many args.
4081 * Let's terminate the string, print the offending part then cut the
4082 * last arg.
4083 */
4084 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4085 line++;
4086 *line = '\0';
4087
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004088 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004089 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 args[arg] = line;
4092 }
4093
Willy Tarreau540abe42007-05-02 20:50:16 +02004094 /* zero out remaining args and ensure that at least one entry
4095 * is zeroed out.
4096 */
4097 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098 args[arg] = line;
4099 }
4100
Willy Tarreau3842f002009-06-14 11:39:52 +02004101 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004102 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004103 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004104 for (arg=0; *args[arg+1]; arg++)
4105 args[arg] = args[arg+1]; // shift args after inversion
4106 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004107 else if (!strcmp(args[0], "default")) {
4108 kwm = KWM_DEF;
4109 for (arg=0; *args[arg+1]; arg++)
4110 args[arg] = args[arg+1]; // shift args after inversion
4111 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004112
Willy Tarreau3842f002009-06-14 11:39:52 +02004113 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4114 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004116 }
4117
Willy Tarreau977b8e42006-12-29 14:19:17 +01004118 if (!strcmp(args[0], "listen") ||
4119 !strcmp(args[0], "frontend") ||
4120 !strcmp(args[0], "backend") ||
4121 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004122 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004123 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004124 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004125 cursection = strdup(args[0]);
4126 }
4127 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004129 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004130 cursection = strdup(args[0]);
4131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 /* else it's a section keyword */
4133
4134 switch (confsect) {
4135 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004136 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 break;
4138 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004139 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 break;
4141 default:
4142 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004143 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004145
4146 if (err_code & ERR_ABORT)
4147 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004149 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004150 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004152 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004153}
4154
Willy Tarreaubb925012009-07-23 13:36:36 +02004155/*
4156 * Returns the error code, 0 if OK, or any combination of :
4157 * - ERR_ABORT: must abort ASAP
4158 * - ERR_FATAL: we can continue parsing but not start the service
4159 * - ERR_WARN: a warning has been emitted
4160 * - ERR_ALERT: an alert has been emitted
4161 * Only the two first ones can stop processing, the two others are just
4162 * indicators.
4163 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004164int check_config_validity()
4165{
4166 int cfgerr = 0;
4167 struct proxy *curproxy = NULL;
4168 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004169 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004170 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171
4172 /*
4173 * Now, check for the integrity of all that we have collected.
4174 */
4175
4176 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004177 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004179 /* first, we will invert the proxy list order */
4180 curproxy = NULL;
4181 while (proxy) {
4182 struct proxy *next;
4183
4184 next = proxy->next;
4185 proxy->next = curproxy;
4186 curproxy = proxy;
4187 if (!next)
4188 break;
4189 proxy = next;
4190 }
4191
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004193 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 }
4197
4198 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004199 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004200 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004201 unsigned int next_id;
4202
4203 if (!curproxy->uuid) {
4204 /* proxy ID not set, use automatic numbering with first
4205 * spare entry starting with next_pxid.
4206 */
4207 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4208 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4209 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4210 next_pxid++;
4211 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004212
Willy Tarreaubaaee002006-06-26 02:48:02 +02004213 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004214 /* ensure we don't keep listeners uselessly bound */
4215 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 curproxy = curproxy->next;
4217 continue;
4218 }
4219
Willy Tarreauff01a212009-03-15 13:46:16 +01004220 switch (curproxy->mode) {
4221 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004222 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004223 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004224 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4225 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004226 cfgerr++;
4227 }
4228
4229 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004230 Warning("config : servers will be ignored for %s '%s'.\n",
4231 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004232 break;
4233
4234 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004235 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004236 break;
4237
4238 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004239 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004240 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004241 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4242 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004243 cfgerr++;
4244 }
4245 break;
4246 }
4247
4248 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004249 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4250 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 cfgerr++;
4252 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004253
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004254 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004255 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004256 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004257 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4258 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004259 cfgerr++;
4260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004262 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004263 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4264 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004265 cfgerr++;
4266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004268 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004269 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4270 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004271 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004272 }
4273 }
4274 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4275 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4276 /* If no LB algo is set in a backend, and we're not in
4277 * transparent mode, dispatch mode nor proxy mode, we
4278 * want to use balance roundrobin by default.
4279 */
4280 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4281 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 }
4283 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004284
Willy Tarreau82936582007-11-30 15:20:09 +01004285 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4286 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004287 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4288 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004289 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004290 }
4291
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004292 /* if a default backend was specified, let's find it */
4293 if (curproxy->defbe.name) {
4294 struct proxy *target;
4295
Alex Williams96532db2009-11-01 21:27:13 -05004296 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004297 if (!target) {
4298 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4299 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004300 cfgerr++;
4301 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004302 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4303 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004304 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004305 } else {
4306 free(curproxy->defbe.name);
4307 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004308 /* we force the backend to be present on at least all of
4309 * the frontend's processes.
4310 */
4311 target->bind_proc = curproxy->bind_proc ?
4312 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004313 }
4314 }
4315
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004316 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004317 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4318 /* map jump target for ACT_SETBE in req_rep chain */
4319 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004320 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004321 struct proxy *target;
4322
Willy Tarreaua496b602006-12-17 23:15:24 +01004323 if (exp->action != ACT_SETBE)
4324 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004325
Alex Williams96532db2009-11-01 21:27:13 -05004326 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004327 if (!target) {
4328 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4329 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004330 cfgerr++;
4331 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004332 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4333 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004334 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004335 } else {
4336 free((void *)exp->replace);
4337 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004338 /* we force the backend to be present on at least all of
4339 * the frontend's processes.
4340 */
4341 target->bind_proc = curproxy->bind_proc ?
4342 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004343 }
4344 }
4345 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004346
4347 /* find the target proxy for 'use_backend' rules */
4348 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004349 struct proxy *target;
4350
Alex Williams96532db2009-11-01 21:27:13 -05004351 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004352
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004353 if (!target) {
4354 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4355 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004356 cfgerr++;
4357 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004358 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4359 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004360 cfgerr++;
4361 } else {
4362 free((void *)rule->be.name);
4363 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004364 /* we force the backend to be present on at least all of
4365 * the frontend's processes.
4366 */
4367 target->bind_proc = curproxy->bind_proc ?
4368 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004369 }
4370 }
4371
Willy Tarreau2738a142006-07-08 17:28:09 +02004372 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004373 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004374 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004375 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004376 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004377 " | While not properly invalid, you will certainly encounter various problems\n"
4378 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004379 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004380 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004381 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004382 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004383
Willy Tarreau1fa31262007-12-03 00:36:16 +01004384 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4385 * We must still support older configurations, so let's find out whether those
4386 * parameters have been set or must be copied from contimeouts.
4387 */
4388 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004389 if (!curproxy->timeout.tarpit ||
4390 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004391 /* tarpit timeout not set. We search in the following order:
4392 * default.tarpit, curr.connect, default.connect.
4393 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004394 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004395 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004396 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004397 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004398 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004399 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004400 }
4401 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004402 (!curproxy->timeout.queue ||
4403 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004404 /* queue timeout not set. We search in the following order:
4405 * default.queue, curr.connect, default.connect.
4406 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004407 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004408 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004409 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004410 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004411 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004412 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004413 }
4414 }
4415
Willy Tarreauf3c69202006-07-09 16:42:34 +02004416 if (curproxy->options & PR_O_SSL3_CHK) {
4417 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4418 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4419 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4420 }
4421
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004422 /* The small pools required for the capture lists */
4423 if (curproxy->nb_req_cap)
4424 curproxy->req_cap_pool = create_pool("ptrcap",
4425 curproxy->nb_req_cap * sizeof(char *),
4426 MEM_F_SHARED);
4427 if (curproxy->nb_rsp_cap)
4428 curproxy->rsp_cap_pool = create_pool("ptrcap",
4429 curproxy->nb_rsp_cap * sizeof(char *),
4430 MEM_F_SHARED);
4431
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004432 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4433 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4434 MEM_F_SHARED);
4435
Willy Tarreau86034312006-12-29 00:10:33 +01004436 /* for backwards compatibility with "listen" instances, if
4437 * fullconn is not set but maxconn is set, then maxconn
4438 * is used.
4439 */
4440 if (!curproxy->fullconn)
4441 curproxy->fullconn = curproxy->maxconn;
4442
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 /* first, we will invert the servers list order */
4444 newsrv = NULL;
4445 while (curproxy->srv) {
4446 struct server *next;
4447
4448 next = curproxy->srv->next;
4449 curproxy->srv->next = newsrv;
4450 newsrv = curproxy->srv;
4451 if (!next)
4452 break;
4453 curproxy->srv = next;
4454 }
4455
Willy Tarreau20697042007-11-15 23:26:18 +01004456 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004457 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004458
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004459 /* We have to initialize the server lookup mechanism depending
4460 * on what LB algorithm was choosen.
4461 */
4462
4463 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4464 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4465 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004466 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4467 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4468 init_server_map(curproxy);
4469 } else {
4470 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4471 fwrr_init_server_groups(curproxy);
4472 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004473 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004474
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004475 case BE_LB_KIND_LC:
4476 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004477 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004478 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004479
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004480 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004481 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4482 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4483 chash_init_server_tree(curproxy);
4484 } else {
4485 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4486 init_server_map(curproxy);
4487 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004488 break;
4489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490
4491 if (curproxy->options & PR_O_LOGASAP)
4492 curproxy->to_log &= ~LW_BYTES;
4493
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004494 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4495 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4496 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4497 proxy_type_str(curproxy), curproxy->id);
4498 err_code |= ERR_WARN;
4499 }
4500
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004502 * ensure that we're not cross-dressing a TCP server into HTTP.
4503 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004504 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004505 newsrv = curproxy->srv;
4506 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004507 if (!newsrv->puid) {
4508 /* server ID not set, use automatic numbering with first
4509 * spare entry starting with next_svid.
4510 */
4511 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4512 newsrv->conf.id.key = newsrv->puid = next_id;
4513 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4514 next_id++;
4515 }
4516
Willy Tarreau21d2af32008-02-14 20:25:24 +01004517 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004518 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4519 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004520 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004521 }
4522 newsrv = newsrv->next;
4523 }
4524
4525 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 * If this server supports a maxconn parameter, it needs a dedicated
4527 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004528 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 */
4530 newsrv = curproxy->srv;
4531 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004532 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004533 /* Only 'minconn' was specified, or it was higher than or equal
4534 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4535 * this will avoid further useless expensive computations.
4536 */
4537 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004538 } else if (newsrv->maxconn && !newsrv->minconn) {
4539 /* minconn was not specified, so we set it to maxconn */
4540 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004541 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004542 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4543 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004544 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 }
4546
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004547 if (newsrv->trackit) {
4548 struct proxy *px;
4549 struct server *srv;
4550 char *pname, *sname;
4551
4552 pname = newsrv->trackit;
4553 sname = strrchr(pname, '/');
4554
4555 if (sname)
4556 *sname++ = '\0';
4557 else {
4558 sname = pname;
4559 pname = NULL;
4560 }
4561
4562 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004563 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004564 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004565 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4566 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004567 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004568 cfgerr++;
4569 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004570 }
4571 } else
4572 px = curproxy;
4573
4574 srv = findserver(px, sname);
4575 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004576 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4577 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004578 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004579 cfgerr++;
4580 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004581 }
4582
4583 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004584 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004585 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004586 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004587 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004588 cfgerr++;
4589 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004590 }
4591
4592 if (curproxy != px &&
4593 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004594 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004595 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004596 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004597 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004598 cfgerr++;
4599 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004600 }
4601
4602 newsrv->tracked = srv;
4603 newsrv->tracknext = srv->tracknext;
4604 srv->tracknext = newsrv;
4605
4606 free(newsrv->trackit);
4607 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004608 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 newsrv = newsrv->next;
4610 }
4611
Willy Tarreauc1a21672009-08-16 22:37:44 +02004612 if (curproxy->cap & PR_CAP_FE) {
4613 if (curproxy->tcp_req.inspect_delay ||
4614 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4615 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4616
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004617 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004618 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004619 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004620 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004621
4622 /* both TCP and HTTP must check switching rules */
4623 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4624 }
4625
4626 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004627 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004628 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004629 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004630 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004631
4632 /* If the backend does requires RDP cookie persistence, we have to
4633 * enable the corresponding analyser.
4634 */
4635 if (curproxy->options2 & PR_O2_RDPC_PRST)
4636 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4637 }
4638
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004639 listener = NULL;
4640 while (curproxy->listen) {
4641 struct listener *next;
4642
4643 next = curproxy->listen->next;
4644 curproxy->listen->next = listener;
4645 listener = curproxy->listen;
4646
4647 if (!next)
4648 break;
4649
4650 curproxy->listen = next;
4651 }
4652
Willy Tarreaue6b98942007-10-29 01:09:36 +01004653 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004654 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004655 listener = curproxy->listen;
4656 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004657 if (!listener->luid) {
4658 /* listener ID not set, use automatic numbering with first
4659 * spare entry starting with next_luid.
4660 */
4661 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4662 listener->conf.id.key = listener->luid = next_id;
4663 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4664 next_id++;
4665 }
4666
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004667 /* enable separate counters */
4668 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4669 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4670 if (!listener->name) {
4671 sprintf(trash, "sock-%d", listener->luid);
4672 listener->name = strdup(trash);
4673 }
4674 }
4675
Willy Tarreaue6b98942007-10-29 01:09:36 +01004676 if (curproxy->options & PR_O_TCP_NOLING)
4677 listener->options |= LI_O_NOLINGER;
4678 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004679 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004680 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004681 listener->accept = event_accept;
4682 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004683 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004684 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004685
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004686 /* smart accept mode is automatic in HTTP mode */
4687 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4688 (curproxy->mode == PR_MODE_HTTP &&
4689 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4690 listener->options |= LI_O_NOQUICKACK;
4691
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004692 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004693 listener = listener->next;
4694 }
4695
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696 curproxy = curproxy->next;
4697 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004698
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004699 /*
4700 * Recount currently required checks.
4701 */
4702
4703 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4704 int optnum;
4705
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004706 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4707 if (curproxy->options & cfg_opts[optnum].val)
4708 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004709
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004710 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4711 if (curproxy->options2 & cfg_opts2[optnum].val)
4712 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004713 }
4714
Willy Tarreaubb925012009-07-23 13:36:36 +02004715 if (cfgerr > 0)
4716 err_code |= ERR_ALERT | ERR_FATAL;
4717 out:
4718 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004719}
4720
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004721/*
4722 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4723 * parsing sessions.
4724 */
4725void cfg_register_keywords(struct cfg_kw_list *kwl)
4726{
4727 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4728}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004730/*
4731 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4732 */
4733void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4734{
4735 LIST_DEL(&kwl->list);
4736 LIST_INIT(&kwl->list);
4737}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738
4739/*
4740 * Local variables:
4741 * c-indent-level: 8
4742 * c-basic-offset: 8
4743 * End:
4744 */