blob: 109c0583dfbf7948693b8029b193ba02647ed0a9 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020043#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020045#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020046#include <proto/lb_fwlc.h>
47#include <proto/lb_fwrr.h>
48#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010050#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020051#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010052#include <proto/protocols.h>
53#include <proto/proto_tcp.h>
54#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010055#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010057#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010059#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060
61
Willy Tarreauf3c69202006-07-09 16:42:34 +020062/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
63 * ssl-hello-chk option to ensure that the remote server speaks SSL.
64 *
65 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
66 */
67const char sslv3_client_hello_pkt[] = {
68 "\x16" /* ContentType : 0x16 = Hanshake */
69 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
70 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
71 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
72 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
73 "\x03\x00" /* Hello Version : 0x0300 = v3 */
74 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
75 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
76 "\x00" /* Session ID length : empty (no session ID) */
77 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
78 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
79 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
80 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
81 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
82 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
83 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
84 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
85 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
86 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
87 "\x00\x38" "\x00\x39" "\x00\x3A"
88 "\x01" /* Compression Length : 0x01 = 1 byte for types */
89 "\x00" /* Compression Type : 0x00 = NULL compression */
90};
91
Willy Tarreau3842f002009-06-14 11:39:52 +020092/* various keyword modifiers */
93enum kw_mod {
94 KWM_STD = 0, /* normal */
95 KWM_NO, /* "no" prefixed before the keyword */
96 KWM_DEF, /* "default" prefixed before the keyword */
97};
98
Willy Tarreau13943ab2006-12-31 00:24:10 +010099/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100100struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100101 const char *name;
102 unsigned int val;
103 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100104 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105};
106
107/* proxy->options */
108static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100109{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100111 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100112 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100114 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
115 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100116 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100117 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
118 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100120 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100121 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
122 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100123 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100124 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
125 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100126#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100127 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100128#endif
129
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100130 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100131};
132
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100133/* proxy->options2 */
134static const struct cfg_opt cfg_opts2[] =
135{
136#ifdef CONFIG_HAP_LINUX_SPLICE
137 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
138 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
140#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200141 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
142 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200143 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
144 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200145 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200146 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200147 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200148 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200149 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100150 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151 { NULL, 0, 0, 0 }
152};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200153
Willy Tarreau6daf3432008-01-22 16:44:08 +0100154static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
156int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100157int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200158
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200159/* List head of all known configuration keywords */
160static struct cfg_kw_list cfg_keywords = {
161 .list = LIST_HEAD_INIT(cfg_keywords.list)
162};
163
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164/*
165 * converts <str> to a list of listeners which are dynamically allocated.
166 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
167 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
168 * - <port> is a numerical port from 1 to 65535 ;
169 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
170 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200171 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200173static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174{
175 struct listener *l;
176 char *c, *next, *range, *dupstr;
177 int port, end;
178
179 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200180
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181 while (next && *next) {
182 struct sockaddr_storage ss;
183
184 str = next;
185 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100186 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 *next++ = 0;
188 }
189
190 /* 2) look for the addr/port delimiter, it's the last colon. */
191 if ((range = strrchr(str, ':')) == NULL) {
192 Alert("Missing port number: '%s'\n", str);
193 goto fail;
194 }
195
196 *range++ = 0;
197
198 if (strrchr(str, ':') != NULL) {
199 /* IPv6 address contains ':' */
200 memset(&ss, 0, sizeof(ss));
201 ss.ss_family = AF_INET6;
202
203 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
204 Alert("Invalid server address: '%s'\n", str);
205 goto fail;
206 }
207 }
208 else {
209 memset(&ss, 0, sizeof(ss));
210 ss.ss_family = AF_INET;
211
212 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
213 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
214 }
215 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
216 struct hostent *he;
217
218 if ((he = gethostbyname(str)) == NULL) {
219 Alert("Invalid server name: '%s'\n", str);
220 goto fail;
221 }
222 else
223 ((struct sockaddr_in *)&ss)->sin_addr =
224 *(struct in_addr *) *(he->h_addr_list);
225 }
226 }
227
228 /* 3) look for the port-end delimiter */
229 if ((c = strchr(range, '-')) != NULL) {
230 *c++ = 0;
231 end = atol(c);
232 }
233 else {
234 end = atol(range);
235 }
236
237 port = atol(range);
238
239 if (port < 1 || port > 65535) {
240 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
241 goto fail;
242 }
243
244 if (end < 1 || end > 65535) {
245 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
246 goto fail;
247 }
248
249 for (; port <= end; port++) {
250 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200251 l->next = curproxy->listen;
252 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
254 l->fd = -1;
255 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100256 l->state = LI_INIT;
257
258 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100260 tcpv6_add_listener(l);
261 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100263 tcpv4_add_listener(l);
264 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200265
Willy Tarreaue6b98942007-10-29 01:09:36 +0100266 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 } /* end for(port) */
268 } /* end while(next) */
269 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200270 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 fail:
272 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200273 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274}
275
Willy Tarreau977b8e42006-12-29 14:19:17 +0100276/*
277 * Sends a warning if proxy <proxy> does not have at least one of the
278 * capabilities in <cap>. An optionnal <hint> may be added at the end
279 * of the warning to help the user. Returns 1 if a warning was emitted
280 * or 0 if the condition is valid.
281 */
282int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
283{
284 char *msg;
285
286 switch (cap) {
287 case PR_CAP_BE: msg = "no backend"; break;
288 case PR_CAP_FE: msg = "no frontend"; break;
289 case PR_CAP_RS: msg = "no ruleset"; break;
290 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
291 default: msg = "not enough"; break;
292 }
293
294 if (!(proxy->cap & cap)) {
295 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100296 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100297 return 1;
298 }
299 return 0;
300}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301
Willy Tarreau61d18892009-03-31 10:49:21 +0200302/* Report a warning if a rule is placed after a 'block' rule.
303 * Return 1 if the warning has been emitted, otherwise 0.
304 */
305int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
306{
307 if (!LIST_ISEMPTY(&proxy->block_cond)) {
308 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
309 file, line, arg);
310 return 1;
311 }
312 return 0;
313}
314
315/* Report a warning if a rule is placed after a reqrewrite rule.
316 * Return 1 if the warning has been emitted, otherwise 0.
317 */
318int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
319{
320 if (proxy->req_exp) {
321 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
322 file, line, arg);
323 return 1;
324 }
325 return 0;
326}
327
328/* Report a warning if a rule is placed after a reqadd rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
331int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
332{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100333 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a redirect rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
344int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
345{
346 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a 'use_backend' rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
357int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
358{
359 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* report a warning if a block rule is dangerously placed */
368int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
369{
370 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
371 warnif_rule_after_reqadd(proxy, file, line, arg) ||
372 warnif_rule_after_redirect(proxy, file, line, arg) ||
373 warnif_rule_after_use_backend(proxy, file, line, arg);
374}
375
376/* report a warning if a reqxxx rule is dangerously placed */
377int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
378{
379 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
380 warnif_rule_after_redirect(proxy, file, line, arg) ||
381 warnif_rule_after_use_backend(proxy, file, line, arg);
382}
383
384/* report a warning if a reqadd rule is dangerously placed */
385int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
386{
387 return warnif_rule_after_redirect(proxy, file, line, arg) ||
388 warnif_rule_after_use_backend(proxy, file, line, arg);
389}
390
Willy Tarreaubaaee002006-06-26 02:48:02 +0200391/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200392 * parse a line in a <global> section. Returns the error code, 0 if OK, or
393 * any combination of :
394 * - ERR_ABORT: must abort ASAP
395 * - ERR_FATAL: we can continue parsing but not start the service
396 * - ERR_WARN: a warning has been emitted
397 * - ERR_ALERT: an alert has been emitted
398 * Only the two first ones can stop processing, the two others are just
399 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200400 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200401int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200402{
Willy Tarreau058e9072009-07-20 09:30:05 +0200403 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200404
405 if (!strcmp(args[0], "global")) { /* new section */
406 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200408 }
409 else if (!strcmp(args[0], "daemon")) {
410 global.mode |= MODE_DAEMON;
411 }
412 else if (!strcmp(args[0], "debug")) {
413 global.mode |= MODE_DEBUG;
414 }
415 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100416 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200417 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200418 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100419 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200420 }
421 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100422 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200424 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100425 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100427 else if (!strcmp(args[0], "nosplice")) {
428 global.tune.options &= ~GTUNE_USE_SPLICE;
429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200430 else if (!strcmp(args[0], "quiet")) {
431 global.mode |= MODE_QUIET;
432 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200433 else if (!strcmp(args[0], "tune.maxpollevents")) {
434 if (global.tune.maxpollevents != 0) {
435 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200436 err_code |= ERR_ALERT;
437 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200438 }
439 if (*(args[1]) == 0) {
440 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200441 err_code |= ERR_ALERT | ERR_FATAL;
442 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200443 }
444 global.tune.maxpollevents = atol(args[1]);
445 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100446 else if (!strcmp(args[0], "tune.maxaccept")) {
447 if (global.tune.maxaccept != 0) {
448 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200449 err_code |= ERR_ALERT;
450 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100451 }
452 if (*(args[1]) == 0) {
453 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 err_code |= ERR_ALERT | ERR_FATAL;
455 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100456 }
457 global.tune.maxaccept = atol(args[1]);
458 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200459 else if (!strcmp(args[0], "tune.bufsize")) {
460 if (*(args[1]) == 0) {
461 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
462 err_code |= ERR_ALERT | ERR_FATAL;
463 goto out;
464 }
465 global.tune.bufsize = atol(args[1]);
466 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
467 global.tune.maxrewrite = global.tune.bufsize / 2;
468 }
469 else if (!strcmp(args[0], "tune.maxrewrite")) {
470 if (*(args[1]) == 0) {
471 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT | ERR_FATAL;
473 goto out;
474 }
475 global.tune.maxrewrite = atol(args[1]);
476 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
477 global.tune.maxrewrite = global.tune.bufsize / 2;
478 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100479 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
480 if (global.tune.client_rcvbuf != 0) {
481 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
482 err_code |= ERR_ALERT;
483 goto out;
484 }
485 if (*(args[1]) == 0) {
486 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489 }
490 global.tune.client_rcvbuf = atol(args[1]);
491 }
492 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
493 if (global.tune.server_rcvbuf != 0) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.tune.server_rcvbuf = atol(args[1]);
504 }
505 else if (!strcmp(args[0], "tune.sndbuf.client")) {
506 if (global.tune.client_sndbuf != 0) {
507 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT;
509 goto out;
510 }
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.client_sndbuf = atol(args[1]);
517 }
518 else if (!strcmp(args[0], "tune.sndbuf.server")) {
519 if (global.tune.server_sndbuf != 0) {
520 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT;
522 goto out;
523 }
524 if (*(args[1]) == 0) {
525 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 global.tune.server_sndbuf = atol(args[1]);
530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531 else if (!strcmp(args[0], "uid")) {
532 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200533 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541 }
542 global.uid = atol(args[1]);
543 }
544 else if (!strcmp(args[0], "gid")) {
545 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200546 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554 }
555 global.gid = atol(args[1]);
556 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200557 /* user/group name handling */
558 else if (!strcmp(args[0], "user")) {
559 struct passwd *ha_user;
560 if (global.uid != 0) {
561 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200562 err_code |= ERR_ALERT;
563 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200564 }
565 errno = 0;
566 ha_user = getpwnam(args[1]);
567 if (ha_user != NULL) {
568 global.uid = (int)ha_user->pw_uid;
569 }
570 else {
571 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 +0200572 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200573 }
574 }
575 else if (!strcmp(args[0], "group")) {
576 struct group *ha_group;
577 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200578 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 err_code |= ERR_ALERT;
580 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200581 }
582 errno = 0;
583 ha_group = getgrnam(args[1]);
584 if (ha_group != NULL) {
585 global.gid = (int)ha_group->gr_gid;
586 }
587 else {
588 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 +0200589 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200590 }
591 }
592 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 else if (!strcmp(args[0], "nbproc")) {
594 if (global.nbproc != 0) {
595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200596 err_code |= ERR_ALERT;
597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 }
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 }
604 global.nbproc = atol(args[1]);
605 }
606 else if (!strcmp(args[0], "maxconn")) {
607 if (global.maxconn != 0) {
608 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200609 err_code |= ERR_ALERT;
610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 }
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 }
617 global.maxconn = atol(args[1]);
618#ifdef SYSTEM_MAXCONN
619 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
620 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);
621 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200622 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624#endif /* SYSTEM_MAXCONN */
625 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100626 else if (!strcmp(args[0], "maxpipes")) {
627 if (global.maxpipes != 0) {
628 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100636 }
637 global.maxpipes = atol(args[1]);
638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 else if (!strcmp(args[0], "ulimit-n")) {
640 if (global.rlimit_nofile != 0) {
641 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200642 err_code |= ERR_ALERT;
643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
645 if (*(args[1]) == 0) {
646 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 }
650 global.rlimit_nofile = atol(args[1]);
651 }
652 else if (!strcmp(args[0], "chroot")) {
653 if (global.chroot != NULL) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.chroot = strdup(args[1]);
664 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200665 else if (!strcmp(args[0], "description")) {
666 int i, len=0;
667 char *d;
668
669 if (!*args[1]) {
670 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
671 file, linenum, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675
676 for(i=1; *args[i]; i++)
677 len += strlen(args[i])+1;
678
679 if (global.desc)
680 free(global.desc);
681
682 global.desc = d = (char *)calloc(1, len);
683
684 d += sprintf(d, "%s", args[1]);
685 for(i=2; *args[i]; i++)
686 d += sprintf(d, " %s", args[i]);
687 }
688 else if (!strcmp(args[0], "node")) {
689 int i;
690 char c;
691
692 for (i=0; args[1][i]; i++) {
693 c = args[1][i];
694 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
695 break;
696 }
697
698 if (!i || args[1][i]) {
699 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
700 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
701 file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705
706 if (global.node)
707 free(global.node);
708
709 global.node = strdup(args[1]);
710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 else if (!strcmp(args[0], "pidfile")) {
712 if (global.pidfile != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.pidfile = strdup(args[1]);
723 }
724 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100725 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200726 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727
728 if (*(args[1]) == 0 || *(args[2]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 }
733
734 facility = get_log_facility(args[2]);
735 if (facility < 0) {
736 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT | ERR_FATAL;
738 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740
741 level = 7; /* max syslog level = debug */
742 if (*(args[3])) {
743 level = get_log_level(args[3]);
744 if (level < 0) {
745 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200746 err_code |= ERR_ALERT | ERR_FATAL;
747 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 }
749 }
750
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200751 minlvl = 0; /* limit syslog level to this level (emerg) */
752 if (*(args[4])) {
753 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200754 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200755 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT | ERR_FATAL;
757 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200758 }
759 }
760
Robert Tsai81ae1952007-12-05 10:47:29 +0100761 if (args[1][0] == '/') {
762 logsrv.u.addr.sa_family = AF_UNIX;
763 logsrv.u.un = *str2sun(args[1]);
764 } else {
765 logsrv.u.addr.sa_family = AF_INET;
766 logsrv.u.in = *str2sa(args[1]);
767 if (!logsrv.u.in.sin_port)
768 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770
771 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100772 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 global.logfac1 = facility;
774 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200775 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100778 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 global.logfac2 = facility;
780 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200781 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 else {
784 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200787 }
788 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
789 if (global.spread_checks != 0) {
790 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT;
792 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200793 }
794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200798 }
799 global.spread_checks = atol(args[1]);
800 if (global.spread_checks < 0 || global.spread_checks > 50) {
801 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200806 struct cfg_kw_list *kwl;
807 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200808 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200809
810 list_for_each_entry(kwl, &cfg_keywords.list, list) {
811 for (index = 0; kwl->kw[index].kw != NULL; index++) {
812 if (kwl->kw[index].section != CFG_GLOBAL)
813 continue;
814 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
815 /* prepare error message just in case */
816 snprintf(trash, sizeof(trash),
817 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200818 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
819 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200820 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200821 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200822 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200823 else if (rc > 0) {
824 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_WARN;
826 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200827 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200828 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200829 }
830 }
831 }
832
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200834 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200836
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 out:
838 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839}
840
Willy Tarreau97cb7802010-01-03 20:23:58 +0100841/* Perform the most basic initialization of a proxy :
842 * memset(), list_init(*), reset_timeouts(*).
843 */
844static void init_new_proxy(struct proxy *p)
845{
846 memset(p, 0, sizeof(struct proxy));
847 LIST_INIT(&p->pendconns);
848 LIST_INIT(&p->acl);
849 LIST_INIT(&p->block_cond);
850 LIST_INIT(&p->redirect_rules);
851 LIST_INIT(&p->mon_fail_cond);
852 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100853 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100854 LIST_INIT(&p->sticking_rules);
855 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100856 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100857 LIST_INIT(&p->req_add);
858 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100859
860 /* Timeouts are defined as -1 */
861 proxy_reset_timeouts(p);
862}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200864void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200865{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100866 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 defproxy.mode = PR_MODE_TCP;
868 defproxy.state = PR_STNEW;
869 defproxy.maxconn = cfg_maxpconn;
870 defproxy.conn_retries = CONN_RETRIES;
871 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100872
873 defproxy.defsrv.inter = DEF_CHKINTR;
874 defproxy.defsrv.fastinter = 0;
875 defproxy.defsrv.downinter = 0;
876 defproxy.defsrv.rise = DEF_RISETIME;
877 defproxy.defsrv.fall = DEF_FALLTIME;
878 defproxy.defsrv.check_port = 0;
879 defproxy.defsrv.maxqueue = 0;
880 defproxy.defsrv.minconn = 0;
881 defproxy.defsrv.maxconn = 0;
882 defproxy.defsrv.slowstart = 0;
883 defproxy.defsrv.onerror = DEF_HANA_ONERR;
884 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
885 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886}
887
888/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100889 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200890 * Returns the error code, 0 if OK, or any combination of :
891 * - ERR_ABORT: must abort ASAP
892 * - ERR_FATAL: we can continue parsing but not start the service
893 * - ERR_WARN: a warning has been emitted
894 * - ERR_ALERT: an alert has been emitted
895 * Only the two first ones can stop processing, the two others are just
896 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200898int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899{
900 static struct proxy *curproxy = NULL;
901 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200902 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100903 int rc;
904 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200905 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906
Willy Tarreau977b8e42006-12-29 14:19:17 +0100907 if (!strcmp(args[0], "listen"))
908 rc = PR_CAP_LISTEN;
909 else if (!strcmp(args[0], "frontend"))
910 rc = PR_CAP_FE | PR_CAP_RS;
911 else if (!strcmp(args[0], "backend"))
912 rc = PR_CAP_BE | PR_CAP_RS;
913 else if (!strcmp(args[0], "ruleset"))
914 rc = PR_CAP_RS;
915 else
916 rc = PR_CAP_NONE;
917
918 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 if (!*args[1]) {
920 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
921 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200923 err_code |= ERR_ALERT | ERR_ABORT;
924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200926
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100927 err = invalid_char(args[1]);
928 if (err) {
929 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
930 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200931 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100932 }
933
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200934 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
935 /*
936 * If there are two proxies with the same name only following
937 * combinations are allowed:
938 *
939 * listen backend frontend ruleset
940 * listen - - - -
941 * backend - - OK -
942 * frontend - OK - -
943 * ruleset - - - -
944 */
945
946 if (!strcmp(curproxy->id, args[1]) &&
947 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
948 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200949 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
950 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
951 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200952 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200953 }
954 }
955
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
957 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200958 err_code |= ERR_ALERT | ERR_ABORT;
959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100961
Willy Tarreau97cb7802010-01-03 20:23:58 +0100962 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 curproxy->next = proxy;
964 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200965 curproxy->conf.file = file;
966 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200967 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100969 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970
971 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100972 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200973 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200974 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200975 err_code |= ERR_FATAL;
976 goto out;
977 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200978 new = curproxy->listen;
979 while (new != last) {
980 new->conf.file = file;
981 new->conf.line = linenum;
982 new = new->next;
983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 global.maxsock++;
985 }
986
987 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100988 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
989
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100992 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200993 curproxy->no_options = defproxy.no_options;
994 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100995 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100996 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200997 curproxy->except_net = defproxy.except_net;
998 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200999 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001000 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001002 if (defproxy.fwdfor_hdr_len) {
1003 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1004 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1005 }
1006
Willy Tarreaub86db342009-11-30 11:50:16 +01001007 if (defproxy.orgto_hdr_len) {
1008 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1009 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1010 }
1011
Willy Tarreau977b8e42006-12-29 14:19:17 +01001012 if (curproxy->cap & PR_CAP_FE) {
1013 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001014 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001015 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001016
1017 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001018 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1019 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001020
1021 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023
Willy Tarreau977b8e42006-12-29 14:19:17 +01001024 if (curproxy->cap & PR_CAP_BE) {
1025 curproxy->fullconn = defproxy.fullconn;
1026 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027
Willy Tarreau977b8e42006-12-29 14:19:17 +01001028 if (defproxy.check_req)
1029 curproxy->check_req = strdup(defproxy.check_req);
1030 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031
Willy Tarreau977b8e42006-12-29 14:19:17 +01001032 if (defproxy.cookie_name)
1033 curproxy->cookie_name = strdup(defproxy.cookie_name);
1034 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001035 if (defproxy.cookie_domain)
1036 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001037
Emeric Brun647caf12009-06-30 17:57:00 +02001038 if (defproxy.rdp_cookie_name)
1039 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1040 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1041
Willy Tarreau01732802007-11-01 22:48:15 +01001042 if (defproxy.url_param_name)
1043 curproxy->url_param_name = strdup(defproxy.url_param_name);
1044 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001045
Benoitaffb4812009-03-25 13:02:10 +01001046 if (defproxy.hh_name)
1047 curproxy->hh_name = strdup(defproxy.hh_name);
1048 curproxy->hh_len = defproxy.hh_len;
1049 curproxy->hh_match_domain = defproxy.hh_match_domain;
1050
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001051 if (defproxy.iface_name)
1052 curproxy->iface_name = strdup(defproxy.iface_name);
1053 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001056 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001057 if (defproxy.capture_name)
1058 curproxy->capture_name = strdup(defproxy.capture_name);
1059 curproxy->capture_namelen = defproxy.capture_namelen;
1060 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001064 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001065 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001066 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001067 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001068 curproxy->uri_auth = defproxy.uri_auth;
1069 curproxy->mon_net = defproxy.mon_net;
1070 curproxy->mon_mask = defproxy.mon_mask;
1071 if (defproxy.monitor_uri)
1072 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1073 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001074 if (defproxy.defbe.name)
1075 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001076 }
1077
1078 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001079 curproxy->timeout.connect = defproxy.timeout.connect;
1080 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001081 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001082 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001083 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001084 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001085 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001086 curproxy->source_addr = defproxy.source_addr;
1087 }
1088
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 curproxy->mode = defproxy.mode;
1090 curproxy->logfac1 = defproxy.logfac1;
1091 curproxy->logsrv1 = defproxy.logsrv1;
1092 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001093 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 curproxy->logfac2 = defproxy.logfac2;
1095 curproxy->logsrv2 = defproxy.logsrv2;
1096 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001097 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001099 curproxy->conf.used_listener_id = EB_ROOT;
1100 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001101
Willy Tarreau93893792009-07-23 13:19:11 +02001102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
1104 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1105 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001106 /* FIXME-20070101: we should do this too at the end of the
1107 * config parsing to free all default values.
1108 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001109 free(defproxy.check_req);
1110 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001111 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001112 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001113 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001114 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001115 free(defproxy.capture_name);
1116 free(defproxy.monitor_uri);
1117 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001118 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001119 free(defproxy.fwdfor_hdr_name);
1120 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001121 free(defproxy.orgto_hdr_name);
1122 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001123
Willy Tarreaua534fea2008-08-03 12:19:50 +02001124 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001125 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001126
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 /* we cannot free uri_auth because it might already be used */
1128 init_default_instance();
1129 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001130 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 else if (curproxy == NULL) {
1134 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138
Willy Tarreau977b8e42006-12-29 14:19:17 +01001139
1140 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001142 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001143 int cur_arg;
1144
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 if (curproxy == &defproxy) {
1146 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001147 err_code |= ERR_ALERT | ERR_FATAL;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001150 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001151 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152
1153 if (strchr(args[1], ':') == NULL) {
1154 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001159
1160 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001161 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
1164 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001165
Willy Tarreau90a570f2009-10-04 20:54:54 +02001166 new_listen = curproxy->listen;
1167 while (new_listen != last_listen) {
1168 new_listen->conf.file = file;
1169 new_listen->conf.line = linenum;
1170 new_listen = new_listen->next;
1171 }
1172
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001173 cur_arg = 2;
1174 while (*(args[cur_arg])) {
1175 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1176#ifdef SO_BINDTODEVICE
1177 struct listener *l;
1178
1179 if (!*args[cur_arg + 1]) {
1180 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001184 }
1185
1186 for (l = curproxy->listen; l != last_listen; l = l->next)
1187 l->interface = strdup(args[cur_arg + 1]);
1188
1189 global.last_checks |= LSTCHK_NETADM;
1190
1191 cur_arg += 2;
1192 continue;
1193#else
1194 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1195 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001198#endif
1199 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001200 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1201#ifdef TCP_MAXSEG
1202 struct listener *l;
1203 int mss;
1204
1205 if (!*args[cur_arg + 1]) {
1206 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1207 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001210 }
1211
1212 mss = str2uic(args[cur_arg + 1]);
1213 if (mss < 1 || mss > 65535) {
1214 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001218 }
1219
1220 for (l = curproxy->listen; l != last_listen; l = l->next)
1221 l->maxseg = mss;
1222
1223 cur_arg += 2;
1224 continue;
1225#else
1226 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1227 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001228 err_code |= ERR_ALERT | ERR_FATAL;
1229 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001230#endif
1231 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001232
1233 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1234#ifdef TCP_DEFER_ACCEPT
1235 struct listener *l;
1236
1237 for (l = curproxy->listen; l != last_listen; l = l->next)
1238 l->options |= LI_O_DEF_ACCEPT;
1239
1240 cur_arg ++;
1241 continue;
1242#else
1243 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1244 file, linenum, args[0], args[cur_arg]);
1245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto out;
1247#endif
1248 }
1249
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001250 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001251#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001252 struct listener *l;
1253
1254 for (l = curproxy->listen; l != last_listen; l = l->next)
1255 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001256
1257 cur_arg ++;
1258 continue;
1259#else
1260 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1261 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001264#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001266
1267 if (!strcmp(args[cur_arg], "name")) {
1268 struct listener *l;
1269
1270 for (l = curproxy->listen; l != last_listen; l = l->next)
1271 l->name = strdup(args[cur_arg + 1]);
1272
1273 cur_arg += 2;
1274 continue;
1275 }
1276
1277 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001278 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001279 struct listener *l;
1280
1281 if (curproxy->listen->next != last_listen) {
1282 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1283 file, linenum, args[cur_arg]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287
1288 if (!*args[cur_arg + 1]) {
1289 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1290 file, linenum, args[cur_arg]);
1291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
1293 }
1294
1295 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001296 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001297
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001298 if (curproxy->listen->luid <= 0) {
1299 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001300 file, linenum);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
1304
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001305 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1306 if (node) {
1307 l = container_of(node, struct listener, conf.id);
1308 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1309 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
1312 }
1313 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1314
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001315 cur_arg += 2;
1316 continue;
1317 }
1318
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001319 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 +01001320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 }
1327 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1328 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1329 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001334 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001335 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001336
Willy Tarreaubaaee002006-06-26 02:48:02 +02001337 /* flush useless bits */
1338 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001341 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001342 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001344
Willy Tarreau1c47f852006-07-09 08:22:27 +02001345 if (!*args[1]) {
1346 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001350 }
1351
Willy Tarreaua534fea2008-08-03 12:19:50 +02001352 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001353 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001354 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001355 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001356 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1357
Willy Tarreau93893792009-07-23 13:19:11 +02001358 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1361 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1362 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1363 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1364 else {
1365 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
1369 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001370 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001371 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001372
1373 if (curproxy == &defproxy) {
1374 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1375 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001378 }
1379
1380 if (!*args[1]) {
1381 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1382 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001385 }
1386
1387 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001388 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001389
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001390 if (curproxy->uuid <= 0) {
1391 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001392 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001395 }
1396
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001397 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1398 if (node) {
1399 struct proxy *target = container_of(node, struct proxy, conf.id);
1400 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1401 file, linenum, proxy_type_str(curproxy), curproxy->id,
1402 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1403 err_code |= ERR_ALERT | ERR_FATAL;
1404 goto out;
1405 }
1406 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001407 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001408 else if (!strcmp(args[0], "description")) {
1409 int i, len=0;
1410 char *d;
1411
1412 if (!*args[1]) {
1413 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1414 file, linenum, args[0]);
1415 return -1;
1416 }
1417
1418 for(i=1; *args[i]; i++)
1419 len += strlen(args[i])+1;
1420
1421 d = (char *)calloc(1, len);
1422 curproxy->desc = d;
1423
1424 d += sprintf(d, "%s", args[1]);
1425 for(i=2; *args[i]; i++)
1426 d += sprintf(d, " %s", args[i]);
1427
1428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1430 curproxy->state = PR_STSTOPPED;
1431 }
1432 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1433 curproxy->state = PR_STNEW;
1434 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001435 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1436 int cur_arg = 1;
1437 unsigned int set = 0;
1438
1439 while (*args[cur_arg]) {
1440 int u;
1441 if (strcmp(args[cur_arg], "all") == 0) {
1442 set = 0;
1443 break;
1444 }
1445 else if (strcmp(args[cur_arg], "odd") == 0) {
1446 set |= 0x55555555;
1447 }
1448 else if (strcmp(args[cur_arg], "even") == 0) {
1449 set |= 0xAAAAAAAA;
1450 }
1451 else {
1452 u = str2uic(args[cur_arg]);
1453 if (u < 1 || u > 32) {
1454 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001456 err_code |= ERR_ALERT | ERR_FATAL;
1457 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001458 }
1459 if (u > global.nbproc) {
1460 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1461 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001462 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001463 }
1464 set |= 1 << (u - 1);
1465 }
1466 cur_arg++;
1467 }
1468 curproxy->bind_proc = set;
1469 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001470 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001471 if (curproxy == &defproxy) {
1472 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001475 }
1476
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001477 err = invalid_char(args[1]);
1478 if (err) {
1479 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1480 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001481 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001482 }
1483
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001484 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1485 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1486 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001487 err_code |= ERR_ALERT | ERR_FATAL;
1488 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001489 }
1490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1492 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001495 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001496
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 if (*(args[1]) == 0) {
1498 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1499 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001500 err_code |= ERR_ALERT | ERR_FATAL;
1501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001503
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001504 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001505 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506 curproxy->cookie_name = strdup(args[1]);
1507 curproxy->cookie_len = strlen(curproxy->cookie_name);
1508
1509 cur_arg = 2;
1510 while (*(args[cur_arg])) {
1511 if (!strcmp(args[cur_arg], "rewrite")) {
1512 curproxy->options |= PR_O_COOK_RW;
1513 }
1514 else if (!strcmp(args[cur_arg], "indirect")) {
1515 curproxy->options |= PR_O_COOK_IND;
1516 }
1517 else if (!strcmp(args[cur_arg], "insert")) {
1518 curproxy->options |= PR_O_COOK_INS;
1519 }
1520 else if (!strcmp(args[cur_arg], "nocache")) {
1521 curproxy->options |= PR_O_COOK_NOC;
1522 }
1523 else if (!strcmp(args[cur_arg], "postonly")) {
1524 curproxy->options |= PR_O_COOK_POST;
1525 }
1526 else if (!strcmp(args[cur_arg], "prefix")) {
1527 curproxy->options |= PR_O_COOK_PFX;
1528 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001529 else if (!strcmp(args[cur_arg], "domain")) {
1530 if (!*args[cur_arg + 1]) {
1531 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1532 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001535 }
1536
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001537 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001538 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001539 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1540 " dots nor does not start with a dot."
1541 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001542 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001543 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001544 }
1545
1546 err = invalid_domainchar(args[cur_arg + 1]);
1547 if (err) {
1548 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1549 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001552 }
1553
Willy Tarreau68a897b2009-12-03 23:28:34 +01001554 if (!curproxy->cookie_domain) {
1555 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1556 } else {
1557 /* one domain was already specified, add another one by
1558 * building the string which will be returned along with
1559 * the cookie.
1560 */
1561 char *new_ptr;
1562 int new_len = strlen(curproxy->cookie_domain) +
1563 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1564 new_ptr = malloc(new_len);
1565 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1566 free(curproxy->cookie_domain);
1567 curproxy->cookie_domain = new_ptr;
1568 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001569 cur_arg++;
1570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001572 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 }
1577 cur_arg++;
1578 }
1579 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1580 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1581 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001582 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 }
1584
1585 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1586 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1587 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001588 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 }
1590 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001591 else if (!strcmp(args[0], "persist")) { /* persist */
1592 if (*(args[1]) == 0) {
1593 Alert("parsing [%s:%d] : missing persist method.\n",
1594 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001597 }
1598
1599 if (!strncmp(args[1], "rdp-cookie", 10)) {
1600 curproxy->options2 |= PR_O2_RDPC_PRST;
1601
Emeric Brunb982a3d2010-01-04 15:45:53 +01001602 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001603 const char *beg, *end;
1604
1605 beg = args[1] + 11;
1606 end = strchr(beg, ')');
1607
1608 if (!end || end == beg) {
1609 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1610 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001611 err_code |= ERR_ALERT | ERR_FATAL;
1612 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001613 }
1614
1615 free(curproxy->rdp_cookie_name);
1616 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1617 curproxy->rdp_cookie_len = end-beg;
1618 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001619 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001620 free(curproxy->rdp_cookie_name);
1621 curproxy->rdp_cookie_name = strdup("msts");
1622 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1623 }
1624 else { /* syntax */
1625 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1626 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001629 }
1630 }
1631 else {
1632 Alert("parsing [%s:%d] : unknown persist method.\n",
1633 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001634 err_code |= ERR_ALERT | ERR_FATAL;
1635 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001636 }
1637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001639 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001641 if (curproxy == &defproxy) {
1642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1643 err_code |= ERR_ALERT | ERR_FATAL;
1644 goto out;
1645 }
1646
Willy Tarreau977b8e42006-12-29 14:19:17 +01001647 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001649
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001651 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
1656 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001657 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 curproxy->appsession_name = strdup(args[1]);
1659 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1660 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001661 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1662 if (err) {
1663 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1664 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001667 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001668 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001669
Willy Tarreau51041c72007-09-09 21:56:53 +02001670 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1671 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_ABORT;
1673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001675
1676 cur_arg = 6;
1677 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001678 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1679 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001680 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001681 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001682 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001683 } else if (!strcmp(args[cur_arg], "prefix")) {
1684 curproxy->options2 |= PR_O2_AS_PFX;
1685 } else if (!strcmp(args[cur_arg], "mode")) {
1686 if (!*args[cur_arg + 1]) {
1687 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1688 file, linenum, args[0], args[cur_arg]);
1689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
1691 }
1692
1693 cur_arg++;
1694 if (!strcmp(args[cur_arg], "query-string")) {
1695 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1696 curproxy->options2 |= PR_O2_AS_M_QS;
1697 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1698 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1699 curproxy->options2 |= PR_O2_AS_M_PP;
1700 } else {
1701 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1702 err_code |= ERR_ALERT | ERR_FATAL;
1703 goto out;
1704 }
1705 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001706 cur_arg++;
1707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 } /* Url App Session */
1709 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001710 if (warnifnotcap(curproxy, PR_CAP_FE, 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 (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 if (*(args[4]) == 0) {
1715 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1716 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001720 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 curproxy->capture_name = strdup(args[2]);
1722 curproxy->capture_namelen = strlen(curproxy->capture_name);
1723 curproxy->capture_len = atol(args[4]);
1724 if (curproxy->capture_len >= CAPTURE_LEN) {
1725 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1726 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->capture_len = CAPTURE_LEN - 1;
1729 }
1730 curproxy->to_log |= LW_COOKIE;
1731 }
1732 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1733 struct cap_hdr *hdr;
1734
1735 if (curproxy == &defproxy) {
1736 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 +02001737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 }
1740
1741 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1742 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1743 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 }
1747
1748 hdr = calloc(sizeof(struct cap_hdr), 1);
1749 hdr->next = curproxy->req_cap;
1750 hdr->name = strdup(args[3]);
1751 hdr->namelen = strlen(args[3]);
1752 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001753 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 hdr->index = curproxy->nb_req_cap++;
1755 curproxy->req_cap = hdr;
1756 curproxy->to_log |= LW_REQHDR;
1757 }
1758 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1759 struct cap_hdr *hdr;
1760
1761 if (curproxy == &defproxy) {
1762 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 +02001763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765 }
1766
1767 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1768 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1769 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 }
1773 hdr = calloc(sizeof(struct cap_hdr), 1);
1774 hdr->next = curproxy->rsp_cap;
1775 hdr->name = strdup(args[3]);
1776 hdr->namelen = strlen(args[3]);
1777 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001778 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 hdr->index = curproxy->nb_rsp_cap++;
1780 curproxy->rsp_cap = hdr;
1781 curproxy->to_log |= LW_RSPHDR;
1782 }
1783 else {
1784 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1785 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 }
1789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001792 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 if (*(args[1]) == 0) {
1795 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1796 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001799 }
1800 curproxy->conn_retries = atol(args[1]);
1801 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001802 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1803 int pol = ACL_COND_NONE;
1804 struct acl_cond *cond;
1805
Willy Tarreaub099aca2008-10-12 17:26:37 +02001806 if (curproxy == &defproxy) {
1807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001810 }
1811
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001812 if (!strcmp(args[1], "if"))
1813 pol = ACL_COND_IF;
1814 else if (!strcmp(args[1], "unless"))
1815 pol = ACL_COND_UNLESS;
1816
1817 if (pol == ACL_COND_NONE) {
1818 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1819 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001822 }
1823
1824 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1825 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1826 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001827 err_code |= ERR_ALERT | ERR_FATAL;
1828 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001829 }
Willy Tarreau88922352009-10-04 22:02:50 +02001830 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001831 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001832 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001833 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001834 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001835 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001836 else if (!strcmp(args[0], "redirect")) {
1837 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001838 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001839 struct redirect_rule *rule;
1840 int cur_arg;
1841 int type = REDIRECT_TYPE_NONE;
1842 int code = 302;
1843 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001844 char *cookie = NULL;
1845 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001846 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001847
1848 cur_arg = 1;
1849 while (*(args[cur_arg])) {
1850 if (!strcmp(args[cur_arg], "location")) {
1851 if (!*args[cur_arg + 1]) {
1852 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1853 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001856 }
1857
1858 type = REDIRECT_TYPE_LOCATION;
1859 cur_arg++;
1860 destination = args[cur_arg];
1861 }
1862 else if (!strcmp(args[cur_arg], "prefix")) {
1863 if (!*args[cur_arg + 1]) {
1864 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1865 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001868 }
1869
1870 type = REDIRECT_TYPE_PREFIX;
1871 cur_arg++;
1872 destination = args[cur_arg];
1873 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001874 else if (!strcmp(args[cur_arg], "set-cookie")) {
1875 if (!*args[cur_arg + 1]) {
1876 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1877 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001880 }
1881
1882 cur_arg++;
1883 cookie = args[cur_arg];
1884 cookie_set = 1;
1885 }
1886 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1887 if (!*args[cur_arg + 1]) {
1888 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1889 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001892 }
1893
1894 cur_arg++;
1895 cookie = args[cur_arg];
1896 cookie_set = 0;
1897 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001898 else if (!strcmp(args[cur_arg],"code")) {
1899 if (!*args[cur_arg + 1]) {
1900 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001904 }
1905 cur_arg++;
1906 code = atol(args[cur_arg]);
1907 if (code < 301 || code > 303) {
1908 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1909 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001910 err_code |= ERR_ALERT | ERR_FATAL;
1911 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001912 }
1913 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001914 else if (!strcmp(args[cur_arg],"drop-query")) {
1915 flags |= REDIRECT_FLAG_DROP_QS;
1916 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001917 else if (!strcmp(args[cur_arg],"append-slash")) {
1918 flags |= REDIRECT_FLAG_APPEND_SLASH;
1919 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001920 else if (!strcmp(args[cur_arg], "if")) {
1921 pol = ACL_COND_IF;
1922 cur_arg++;
1923 break;
1924 }
1925 else if (!strcmp(args[cur_arg], "unless")) {
1926 pol = ACL_COND_UNLESS;
1927 cur_arg++;
1928 break;
1929 }
1930 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001931 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001932 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001935 }
1936 cur_arg++;
1937 }
1938
1939 if (type == REDIRECT_TYPE_NONE) {
1940 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1941 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001944 }
1945
Willy Tarreauf285f542010-01-03 20:03:03 +01001946 if (pol != ACL_COND_NONE &&
1947 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001948 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001952 }
1953
Willy Tarreauf285f542010-01-03 20:03:03 +01001954 if (cond) {
1955 cond->file = file;
1956 cond->line = linenum;
1957 curproxy->acl_requires |= cond->requires;
1958 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001959 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1960 rule->cond = cond;
1961 rule->rdr_str = strdup(destination);
1962 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001963 if (cookie) {
1964 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1965 * a clear consists in appending "; Max-Age=0" at the end.
1966 */
1967 rule->cookie_len = strlen(cookie);
1968 if (cookie_set)
1969 rule->cookie_str = strdup(cookie);
1970 else {
1971 rule->cookie_str = malloc(rule->cookie_len + 12);
1972 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1973 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1974 rule->cookie_len += 11;
1975 }
1976 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001977 rule->type = type;
1978 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001979 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001980 LIST_INIT(&rule->list);
1981 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001982 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001983 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001984 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001985 int pol = ACL_COND_NONE;
1986 struct acl_cond *cond;
1987 struct switching_rule *rule;
1988
Willy Tarreaub099aca2008-10-12 17:26:37 +02001989 if (curproxy == &defproxy) {
1990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001993 }
1994
Willy Tarreau55ea7572007-06-17 19:56:27 +02001995 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001996 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001997
1998 if (*(args[1]) == 0) {
1999 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002002 }
2003
2004 if (!strcmp(args[2], "if"))
2005 pol = ACL_COND_IF;
2006 else if (!strcmp(args[2], "unless"))
2007 pol = ACL_COND_UNLESS;
2008
2009 if (pol == ACL_COND_NONE) {
2010 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2011 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002014 }
2015
2016 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002017 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002018 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002021 }
2022
Willy Tarreau88922352009-10-04 22:02:50 +02002023 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002024 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002025 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02002026 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02002027 struct acl *acl;
2028 const char *name;
2029
2030 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2031 name = acl ? acl->name : "(unknown)";
2032 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
2033 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02002035 }
2036
Willy Tarreau55ea7572007-06-17 19:56:27 +02002037 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2038 rule->cond = cond;
2039 rule->be.name = strdup(args[1]);
2040 LIST_INIT(&rule->list);
2041 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2042 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002043 else if (!strcmp(args[0], "force-persist")) {
2044 int pol = ACL_COND_NONE;
2045 struct acl_cond *cond;
2046 struct force_persist_rule *rule;
2047
2048 if (curproxy == &defproxy) {
2049 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
2052 }
2053
2054 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2055 err_code |= ERR_WARN;
2056
2057 if (!strcmp(args[1], "if"))
2058 pol = ACL_COND_IF;
2059 else if (!strcmp(args[1], "unless"))
2060 pol = ACL_COND_UNLESS;
2061
2062 if (pol == ACL_COND_NONE) {
2063 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2064 file, linenum, args[0]);
2065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
2067 }
2068
2069 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
2070 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2071 file, linenum);
2072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
2074 }
2075
2076 cond->file = file;
2077 cond->line = linenum;
2078 curproxy->acl_requires |= cond->requires;
2079 if (cond->requires & ACL_USE_RTR_ANY) {
2080 struct acl *acl;
2081 const char *name;
2082
2083 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2084 name = acl ? acl->name : "(unknown)";
2085 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
2086 file, linenum, name);
2087 err_code |= ERR_WARN;
2088 }
2089
2090 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2091 rule->cond = cond;
2092 LIST_INIT(&rule->list);
2093 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2094 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002095 else if (!strcmp(args[0], "stick-table")) {
2096 int myidx = 1;
2097
2098 curproxy->table.type = (unsigned int)-1;
2099 while (*args[myidx]) {
2100 const char *err;
2101
2102 if (strcmp(args[myidx], "size") == 0) {
2103 myidx++;
2104 if (!*(args[myidx])) {
2105 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2106 file, linenum, args[myidx-1]);
2107 err_code |= ERR_ALERT | ERR_FATAL;
2108 goto out;
2109 }
2110 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2111 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2112 file, linenum, *err, args[myidx-1]);
2113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
2115 }
2116 }
2117 else if (strcmp(args[myidx], "expire") == 0) {
2118 myidx++;
2119 if (!*(args[myidx])) {
2120 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2121 file, linenum, args[myidx-1]);
2122 err_code |= ERR_ALERT | ERR_FATAL;
2123 goto out;
2124 }
2125 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2126 if (err) {
2127 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2128 file, linenum, *err, args[myidx-1]);
2129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
2131 }
2132 curproxy->table.expire = val;
2133 }
2134 else if (strcmp(args[myidx], "nopurge") == 0) {
2135 curproxy->table.nopurge = 1;
2136 }
2137 else if (strcmp(args[myidx], "type") == 0) {
2138 myidx++;
2139 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2140 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2141 file, linenum, args[myidx]);
2142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
2144 }
2145 }
2146 myidx++;
2147 }
2148
2149 if (!curproxy->table.size) {
2150 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2151 file, linenum);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
2156 if (curproxy->table.type == (unsigned int)-1) {
2157 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2158 file, linenum);
2159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
2161 }
2162 }
2163 else if (!strcmp(args[0], "stick")) {
2164 int pol = ACL_COND_NONE;
2165 struct acl_cond *cond = NULL;
2166 struct sticking_rule *rule;
2167 struct pattern_expr *expr;
2168 int myidx = 0;
2169 const char *name = NULL;
2170 int flags;
2171
2172 if (curproxy == &defproxy) {
2173 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
2177
2178 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2179 err_code |= ERR_WARN;
2180 goto out;
2181 }
2182
2183 myidx++;
2184 if ((strcmp(args[myidx], "store") == 0) ||
2185 (strcmp(args[myidx], "store-request") == 0)) {
2186 myidx++;
2187 flags = STK_IS_STORE;
2188 }
2189 else if (strcmp(args[myidx], "store-response") == 0) {
2190 myidx++;
2191 flags = STK_IS_STORE | STK_ON_RSP;
2192 }
2193 else if (strcmp(args[myidx], "match") == 0) {
2194 myidx++;
2195 flags = STK_IS_MATCH;
2196 }
2197 else if (strcmp(args[myidx], "on") == 0) {
2198 myidx++;
2199 flags = STK_IS_MATCH | STK_IS_STORE;
2200 }
2201 else {
2202 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2203 err_code |= ERR_ALERT | ERR_FATAL;
2204 goto out;
2205 }
2206
2207 if (*(args[myidx]) == 0) {
2208 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
2211 }
2212
2213 expr = pattern_parse_expr(args, &myidx);
2214 if (!expr) {
2215 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
2218 }
2219
2220 if (flags & STK_ON_RSP) {
2221 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2222 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2223 file, linenum, args[0], expr->fetch->kw);
2224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
2226 }
2227 } else {
2228 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2229 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2230 file, linenum, args[0], expr->fetch->kw);
2231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
2233 }
2234 }
2235
2236 if (strcmp(args[myidx], "table") == 0) {
2237 myidx++;
2238 name = args[myidx++];
2239 }
2240
2241 if (*(args[myidx]) == 0)
2242 pol = ACL_COND_NONE;
2243 else if (strcmp(args[myidx], "if") == 0)
2244 pol = ACL_COND_IF;
2245 else if (strcmp(args[myidx], "unless") == 0)
2246 pol = ACL_COND_UNLESS;
2247 else {
2248 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2249 file, linenum, args[0], args[myidx]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253
2254 if (pol != ACL_COND_NONE) {
2255 myidx++;
2256 if ((cond = parse_acl_cond((const char **)args + myidx, &curproxy->acl, pol)) == NULL) {
2257 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2258 file, linenum, args[0]);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
2263 cond->file = file;
2264 cond->line = linenum;
2265 curproxy->acl_requires |= cond->requires;
2266 if (cond->requires & ACL_USE_RTR_ANY) {
2267 struct acl *acl;
2268 const char *name;
2269
2270 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2271 name = acl ? acl->name : "(unknown)";
2272 Warning("parsing [%s:%d] : '%s' : acl '%s' involves some response-only criteria which will be ignored.\n",
2273 file, linenum, args[0], name);
2274 err_code |= ERR_WARN;
2275 }
2276 }
2277 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2278 rule->cond = cond;
2279 rule->expr = expr;
2280 rule->flags = flags;
2281 rule->table.name = name ? strdup(name) : NULL;
2282 LIST_INIT(&rule->list);
2283 if (flags & STK_ON_RSP)
2284 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2285 else
2286 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002289 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2293 curproxy->uri_auth = NULL; /* we must detach from the default config */
2294
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002295 if (!*args[1]) {
2296 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 } else if (!strcmp(args[1], "uri")) {
2298 if (*(args[2]) == 0) {
2299 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2303 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_ALERT | ERR_ABORT;
2305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 }
2307 } else if (!strcmp(args[1], "realm")) {
2308 if (*(args[2]) == 0) {
2309 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002314 err_code |= ERR_ALERT | ERR_ABORT;
2315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002317 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002318 unsigned interval;
2319
2320 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2321 if (err) {
2322 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2323 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002326 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_ALERT | ERR_ABORT;
2329 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 } else if (!strcmp(args[1], "auth")) {
2332 if (*(args[2]) == 0) {
2333 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002334 err_code |= ERR_ALERT | ERR_FATAL;
2335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2337 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_ABORT;
2339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
2341 } else if (!strcmp(args[1], "scope")) {
2342 if (*(args[2]) == 0) {
2343 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2347 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_ABORT;
2349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 }
2351 } else if (!strcmp(args[1], "enable")) {
2352 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2353 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_ABORT;
2355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002357 } else if (!strcmp(args[1], "hide-version")) {
2358 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_ABORT;
2361 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002362 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002363 } else if (!strcmp(args[1], "show-legends")) {
2364 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2365 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2366 err_code |= ERR_ALERT | ERR_ABORT;
2367 goto out;
2368 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002369 } else if (!strcmp(args[1], "show-node")) {
2370
2371 if (*args[2]) {
2372 int i;
2373 char c;
2374
2375 for (i=0; args[2][i]; i++) {
2376 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002377 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002378 break;
2379 }
2380
2381 if (!i || args[2][i]) {
2382 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2383 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2384 file, linenum, args[0], args[1]);
2385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
2387 }
2388 }
2389
2390 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2391 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2392 err_code |= ERR_ALERT | ERR_ABORT;
2393 goto out;
2394 }
2395 } else if (!strcmp(args[1], "show-desc")) {
2396 char *desc = NULL;
2397
2398 if (*args[2]) {
2399 int i, len=0;
2400 char *d;
2401
2402 for(i=2; *args[i]; i++)
2403 len += strlen(args[i])+1;
2404
2405 desc = d = (char *)calloc(1, len);
2406
2407 d += sprintf(d, "%s", args[2]);
2408 for(i=3; *args[i]; i++)
2409 d += sprintf(d, " %s", args[i]);
2410 }
2411
2412 if (!*args[2] && !global.desc)
2413 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2414 file, linenum, args[1]);
2415 else {
2416 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2417 free(desc);
2418 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2419 err_code |= ERR_ALERT | ERR_ABORT;
2420 goto out;
2421 }
2422 free(desc);
2423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002425stats_error_parsing:
2426 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2427 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431 }
2432 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002433 int optnum;
2434
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002435 if (*(args[1]) == '\0') {
2436 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2437 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002441
2442 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2443 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002444 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2445 err_code |= ERR_WARN;
2446 goto out;
2447 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002448
Willy Tarreau3842f002009-06-14 11:39:52 +02002449 curproxy->no_options &= ~cfg_opts[optnum].val;
2450 curproxy->options &= ~cfg_opts[optnum].val;
2451
2452 switch (kwm) {
2453 case KWM_STD:
2454 curproxy->options |= cfg_opts[optnum].val;
2455 break;
2456 case KWM_NO:
2457 curproxy->no_options |= cfg_opts[optnum].val;
2458 break;
2459 case KWM_DEF: /* already cleared */
2460 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002461 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002462
Willy Tarreau93893792009-07-23 13:19:11 +02002463 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002464 }
2465 }
2466
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002467 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2468 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002469 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2470 err_code |= ERR_WARN;
2471 goto out;
2472 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002473
Willy Tarreau3842f002009-06-14 11:39:52 +02002474 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2475 curproxy->options2 &= ~cfg_opts2[optnum].val;
2476
2477 switch (kwm) {
2478 case KWM_STD:
2479 curproxy->options2 |= cfg_opts2[optnum].val;
2480 break;
2481 case KWM_NO:
2482 curproxy->no_options2 |= cfg_opts2[optnum].val;
2483 break;
2484 case KWM_DEF: /* already cleared */
2485 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002486 }
Willy Tarreau93893792009-07-23 13:19:11 +02002487 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002488 }
2489 }
2490
Willy Tarreau3842f002009-06-14 11:39:52 +02002491 if (kwm != KWM_STD) {
2492 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002493 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002496 }
2497
Emeric Brun3a058f32009-06-30 18:26:00 +02002498 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002500 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002502 if (*(args[2]) != '\0') {
2503 if (!strcmp(args[2], "clf")) {
2504 curproxy->options2 |= PR_O2_CLFLOG;
2505 } else {
2506 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002509 }
2510 }
2511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 else if (!strcmp(args[1], "tcplog"))
2513 /* generate a detailed TCP log */
2514 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 else if (!strcmp(args[1], "tcpka")) {
2516 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002517 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002518 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002519
2520 if (curproxy->cap & PR_CAP_FE)
2521 curproxy->options |= PR_O_TCP_CLI_KA;
2522 if (curproxy->cap & PR_CAP_BE)
2523 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 }
2525 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_WARN;
2528
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002530 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002531 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002532 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002533 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002534 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 if (!*args[2]) { /* no argument */
2536 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2537 curproxy->check_len = strlen(DEF_CHECK_REQ);
2538 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002539 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 curproxy->check_req = (char *)malloc(reqlen);
2541 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2542 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2543 } else { /* more arguments : METHOD URI [HTTP_VER] */
2544 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2545 if (*args[4])
2546 reqlen += strlen(args[4]);
2547 else
2548 reqlen += strlen("HTTP/1.0");
2549
2550 curproxy->check_req = (char *)malloc(reqlen);
2551 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2552 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2553 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002554 }
2555 else if (!strcmp(args[1], "ssl-hello-chk")) {
2556 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002557 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002559
Willy Tarreaua534fea2008-08-03 12:19:50 +02002560 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002561 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002562 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002563 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002564 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
Willy Tarreau23677902007-05-08 23:50:35 +02002566 else if (!strcmp(args[1], "smtpchk")) {
2567 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002568 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002569 curproxy->options &= ~PR_O_HTTP_CHK;
2570 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002571 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002572 curproxy->options |= PR_O_SMTP_CHK;
2573
2574 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2575 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2576 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2577 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2578 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2579 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2580 curproxy->check_req = (char *)malloc(reqlen);
2581 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2582 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2583 } else {
2584 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2585 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2586 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2587 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2588 }
2589 }
2590 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002591 else if (!strcmp(args[1], "mysql-check")) {
2592 /* use MYSQL request to check servers' health */
2593 free(curproxy->check_req);
2594 curproxy->options &= ~PR_O_HTTP_CHK;
2595 curproxy->options &= ~PR_O_SSL3_CHK;
2596 curproxy->options &= ~PR_O_SMTP_CHK;
2597 curproxy->options2 |= PR_O2_MYSQL_CHK;
2598 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002599 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002600 int cur_arg;
2601
2602 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2603 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002604 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002605
2606 curproxy->options |= PR_O_FWDFOR;
2607
2608 free(curproxy->fwdfor_hdr_name);
2609 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2610 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2611
2612 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2613 cur_arg = 2;
2614 while (*(args[cur_arg])) {
2615 if (!strcmp(args[cur_arg], "except")) {
2616 /* suboption except - needs additional argument for it */
2617 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2618 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2619 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002622 }
2623 /* flush useless bits */
2624 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002625 cur_arg += 2;
2626 } else if (!strcmp(args[cur_arg], "header")) {
2627 /* suboption header - needs additional argument for it */
2628 if (*(args[cur_arg+1]) == 0) {
2629 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2630 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002633 }
2634 free(curproxy->fwdfor_hdr_name);
2635 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2636 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2637 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002638 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002639 /* unknown suboption - catchall */
2640 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2641 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002644 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002645 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002646 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002647 else if (!strcmp(args[1], "originalto")) {
2648 int cur_arg;
2649
2650 /* insert x-original-to field, but not for the IP address listed as an except.
2651 * set default options (ie: bitfield, header name, etc)
2652 */
2653
2654 curproxy->options |= PR_O_ORGTO;
2655
2656 free(curproxy->orgto_hdr_name);
2657 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2658 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2659
2660 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2661 cur_arg = 2;
2662 while (*(args[cur_arg])) {
2663 if (!strcmp(args[cur_arg], "except")) {
2664 /* suboption except - needs additional argument for it */
2665 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2666 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2667 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002670 }
2671 /* flush useless bits */
2672 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2673 cur_arg += 2;
2674 } else if (!strcmp(args[cur_arg], "header")) {
2675 /* suboption header - needs additional argument for it */
2676 if (*(args[cur_arg+1]) == 0) {
2677 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2678 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002681 }
2682 free(curproxy->orgto_hdr_name);
2683 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2684 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2685 cur_arg += 2;
2686 } else {
2687 /* unknown suboption - catchall */
2688 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2689 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002692 }
2693 } /* end while loop */
2694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 else {
2696 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 }
Willy Tarreau93893792009-07-23 13:19:11 +02002700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002702 else if (!strcmp(args[0], "default_backend")) {
2703 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002704 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002705
2706 if (*(args[1]) == 0) {
2707 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002710 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002711 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002712 curproxy->defbe.name = strdup(args[1]);
2713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002718 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2719 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002720 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 /* enable reconnections to dispatch */
2722 curproxy->options |= PR_O_REDISP;
2723 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002724 else if (!strcmp(args[0], "http-check")) {
2725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002727
2728 if (strcmp(args[1], "disable-on-404") == 0) {
2729 /* enable a graceful server shutdown on an HTTP 404 response */
2730 curproxy->options |= PR_O_DISABLE404;
2731 }
2732 else {
2733 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002736 }
2737 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002738 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002743 }
2744
Willy Tarreaub80c2302007-11-30 20:51:32 +01002745 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002747
2748 if (strcmp(args[1], "fail") == 0) {
2749 /* add a condition to fail monitor requests */
2750 int pol = ACL_COND_NONE;
2751 struct acl_cond *cond;
2752
2753 if (!strcmp(args[2], "if"))
2754 pol = ACL_COND_IF;
2755 else if (!strcmp(args[2], "unless"))
2756 pol = ACL_COND_UNLESS;
2757
2758 if (pol == ACL_COND_NONE) {
2759 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2760 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002763 }
2764
2765 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2766 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2767 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002770 }
Willy Tarreau88922352009-10-04 22:02:50 +02002771 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002772 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002773 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002774 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2775 }
2776 else {
2777 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002780 }
2781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782#ifdef TPROXY
2783 else if (!strcmp(args[0], "transparent")) {
2784 /* enable transparent proxy connections */
2785 curproxy->options |= PR_O_TRANSP;
2786 }
2787#endif
2788 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002789 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002791
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 if (*(args[1]) == 0) {
2793 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 }
2797 curproxy->maxconn = atol(args[1]);
2798 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002799 else if (!strcmp(args[0], "backlog")) { /* backlog */
2800 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002802
2803 if (*(args[1]) == 0) {
2804 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002807 }
2808 curproxy->backlog = atol(args[1]);
2809 }
Willy Tarreau86034312006-12-29 00:10:33 +01002810 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002813
Willy Tarreau86034312006-12-29 00:10:33 +01002814 if (*(args[1]) == 0) {
2815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002818 }
2819 curproxy->fullconn = atol(args[1]);
2820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2822 if (*(args[1]) == 0) {
2823 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002827 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2828 if (err) {
2829 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2830 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002833 }
2834 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 }
2836 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2837 if (curproxy == &defproxy) {
2838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002842 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002844
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 if (strchr(args[1], ':') == NULL) {
2846 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 }
2850 curproxy->dispatch_addr = *str2sa(args[1]);
2851 }
2852 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002855
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002856 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002857 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2858 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002863 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2865 err_code |= ERR_WARN;
2866
2867 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2868 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2869 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2870 }
2871 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2872 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2873 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2874 }
2875 else {
2876 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002881 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002883 char *rport, *raddr;
2884 short realport = 0;
2885 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002887 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002892 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894
2895 if (!*args[2]) {
2896 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2897 file, linenum, args[0]);
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 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002901
2902 err = invalid_char(args[1]);
2903 if (err) {
2904 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2905 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002908 }
2909
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2911 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_ABORT;
2913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
2915
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002916 if (!defsrv) {
2917 /* the servers are linked backwards first */
2918 newsrv->next = curproxy->srv;
2919 curproxy->srv = newsrv;
2920 newsrv->proxy = curproxy;
2921 newsrv->conf.file = file;
2922 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002924 LIST_INIT(&newsrv->pendconns);
2925 do_check = 0;
2926 newsrv->state = SRV_RUNNING; /* early server setup */
2927 newsrv->last_change = now.tv_sec;
2928 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002930 /* several ways to check the port component :
2931 * - IP => port=+0, relative
2932 * - IP: => port=+0, relative
2933 * - IP:N => port=N, absolute
2934 * - IP:+N => port=+N, relative
2935 * - IP:-N => port=-N, relative
2936 */
2937 raddr = strdup(args[2]);
2938 rport = strchr(raddr, ':');
2939 if (rport) {
2940 *rport++ = 0;
2941 realport = atol(rport);
2942 if (!isdigit((unsigned char)*rport))
2943 newsrv->state |= SRV_MAPPORTS;
2944 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002946
2947 newsrv->addr = *str2sa(raddr);
2948 newsrv->addr.sin_port = htons(realport);
2949 free(raddr);
2950
2951 newsrv->check_port = curproxy->defsrv.check_port;
2952 newsrv->inter = curproxy->defsrv.inter;
2953 newsrv->fastinter = curproxy->defsrv.fastinter;
2954 newsrv->downinter = curproxy->defsrv.downinter;
2955 newsrv->rise = curproxy->defsrv.rise;
2956 newsrv->fall = curproxy->defsrv.fall;
2957 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2958 newsrv->minconn = curproxy->defsrv.minconn;
2959 newsrv->maxconn = curproxy->defsrv.maxconn;
2960 newsrv->slowstart = curproxy->defsrv.slowstart;
2961 newsrv->onerror = curproxy->defsrv.onerror;
2962 newsrv->consecutive_errors_limit
2963 = curproxy->defsrv.consecutive_errors_limit;
2964 newsrv->uweight = newsrv->iweight
2965 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002967 newsrv->curfd = -1; /* no health-check in progress */
2968 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002970 cur_arg = 3;
2971 } else {
2972 newsrv = &curproxy->defsrv;
2973 cur_arg = 1;
2974 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002975
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002977 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002978 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002979
2980 if (!*args[cur_arg + 1]) {
2981 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2982 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002985 }
2986
2987 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002988 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002989
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002990 if (newsrv->puid <= 0) {
2991 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002992 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002995 }
2996
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002997 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2998 if (node) {
2999 struct server *target = container_of(node, struct server, conf.id);
3000 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3001 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
3005 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003006 cur_arg += 2;
3007 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003008 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 newsrv->cookie = strdup(args[cur_arg + 1]);
3010 newsrv->cklen = strlen(args[cur_arg + 1]);
3011 cur_arg += 2;
3012 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003013 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003014 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3015 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3016 cur_arg += 2;
3017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003019 if (!*args[cur_arg + 1]) {
3020 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3021 file, linenum, args[cur_arg]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003027 if (newsrv->rise <= 0) {
3028 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3029 file, linenum, args[cur_arg]);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
3033
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 newsrv->health = newsrv->rise;
3035 cur_arg += 2;
3036 }
3037 else if (!strcmp(args[cur_arg], "fall")) {
3038 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003039
3040 if (!*args[cur_arg + 1]) {
3041 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3042 file, linenum, args[cur_arg]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046
3047 if (newsrv->fall <= 0) {
3048 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3049 file, linenum, args[cur_arg]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 cur_arg += 2;
3055 }
3056 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003057 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3058 if (err) {
3059 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3060 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003063 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003064 if (val <= 0) {
3065 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3066 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003069 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003070 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 cur_arg += 2;
3072 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003073 else if (!strcmp(args[cur_arg], "fastinter")) {
3074 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3075 if (err) {
3076 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3077 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003080 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003081 if (val <= 0) {
3082 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3083 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003086 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003087 newsrv->fastinter = val;
3088 cur_arg += 2;
3089 }
3090 else if (!strcmp(args[cur_arg], "downinter")) {
3091 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3092 if (err) {
3093 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3094 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003097 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003098 if (val <= 0) {
3099 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3100 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003103 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003104 newsrv->downinter = val;
3105 cur_arg += 2;
3106 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003107 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003108 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003109 cur_arg += 2;
3110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 else if (!strcmp(args[cur_arg], "port")) {
3112 newsrv->check_port = atol(args[cur_arg + 1]);
3113 cur_arg += 2;
3114 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003115 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 newsrv->state |= SRV_BACKUP;
3117 cur_arg ++;
3118 }
3119 else if (!strcmp(args[cur_arg], "weight")) {
3120 int w;
3121 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003122 if (w < 0 || w > 256) {
3123 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003128 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 cur_arg += 2;
3130 }
3131 else if (!strcmp(args[cur_arg], "minconn")) {
3132 newsrv->minconn = atol(args[cur_arg + 1]);
3133 cur_arg += 2;
3134 }
3135 else if (!strcmp(args[cur_arg], "maxconn")) {
3136 newsrv->maxconn = atol(args[cur_arg + 1]);
3137 cur_arg += 2;
3138 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003139 else if (!strcmp(args[cur_arg], "maxqueue")) {
3140 newsrv->maxqueue = atol(args[cur_arg + 1]);
3141 cur_arg += 2;
3142 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003143 else if (!strcmp(args[cur_arg], "slowstart")) {
3144 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003145 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003146 if (err) {
3147 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3148 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003151 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003152 if (val <= 0) {
3153 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3154 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003157 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003158 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003159 cur_arg += 2;
3160 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003161 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003162
3163 if (!*args[cur_arg + 1]) {
3164 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003168 }
3169
3170 newsrv->trackit = strdup(args[cur_arg + 1]);
3171
3172 cur_arg += 2;
3173 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003174 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 global.maxsock++;
3176 do_check = 1;
3177 cur_arg += 1;
3178 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003179 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003180 if (!strcmp(args[cur_arg + 1], "none"))
3181 newsrv->observe = HANA_OBS_NONE;
3182 else if (!strcmp(args[cur_arg + 1], "layer4"))
3183 newsrv->observe = HANA_OBS_LAYER4;
3184 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3185 if (curproxy->mode != PR_MODE_HTTP) {
3186 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3187 file, linenum, args[cur_arg + 1]);
3188 err_code |= ERR_ALERT;
3189 }
3190 newsrv->observe = HANA_OBS_LAYER7;
3191 }
3192 else {
3193 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3194 "'l4events', 'http-responses' but get '%s'\n",
3195 file, linenum, args[cur_arg], args[cur_arg + 1]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198 }
3199
3200 cur_arg += 2;
3201 }
3202 else if (!strcmp(args[cur_arg], "on-error")) {
3203 if (!strcmp(args[cur_arg + 1], "fastinter"))
3204 newsrv->onerror = HANA_ONERR_FASTINTER;
3205 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3206 newsrv->onerror = HANA_ONERR_FAILCHK;
3207 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3208 newsrv->onerror = HANA_ONERR_SUDDTH;
3209 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3210 newsrv->onerror = HANA_ONERR_MARKDWN;
3211 else {
3212 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3213 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3214 file, linenum, args[cur_arg], args[cur_arg + 1]);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
3218
3219 cur_arg += 2;
3220 }
3221 else if (!strcmp(args[cur_arg], "error-limit")) {
3222 if (!*args[cur_arg + 1]) {
3223 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3224 file, linenum, args[cur_arg]);
3225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
3227 }
3228
3229 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3230
3231 if (newsrv->consecutive_errors_limit <= 0) {
3232 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3233 file, linenum, args[cur_arg]);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
3237 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003238 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003239 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003241#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003242 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003243 file, linenum, "source", "usesrc");
3244#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003245 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003247#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 }
3251 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003252 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3253
3254 if (port_low != port_high) {
3255 int i;
3256 if (port_low <= 0 || port_low > 65535 ||
3257 port_high <= 0 || port_high > 65535 ||
3258 port_low > port_high) {
3259 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3260 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003263 }
3264 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3265 for (i = 0; i < newsrv->sport_range->size; i++)
3266 newsrv->sport_range->ports[i] = port_low + i;
3267 }
3268
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003270 while (*(args[cur_arg])) {
3271 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003272#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3273#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003274 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3275 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3276 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003279 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003280#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003281 if (!*args[cur_arg + 1]) {
3282 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3283 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003286 }
3287 if (!strcmp(args[cur_arg + 1], "client")) {
3288 newsrv->state |= SRV_TPROXY_CLI;
3289 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3290 newsrv->state |= SRV_TPROXY_CIP;
3291 } else {
3292 newsrv->state |= SRV_TPROXY_ADDR;
3293 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3294 }
3295 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003296#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003297 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003298#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003299 cur_arg += 2;
3300 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003301#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003302 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003303 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003306#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3307 } /* "usesrc" */
3308
3309 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3310#ifdef SO_BINDTODEVICE
3311 if (!*args[cur_arg + 1]) {
3312 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3313 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003316 }
3317 if (newsrv->iface_name)
3318 free(newsrv->iface_name);
3319
3320 newsrv->iface_name = strdup(args[cur_arg + 1]);
3321 newsrv->iface_len = strlen(newsrv->iface_name);
3322 global.last_checks |= LSTCHK_NETADM;
3323#else
3324 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3325 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003328#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003329 cur_arg += 2;
3330 continue;
3331 }
3332 /* this keyword in not an option of "source" */
3333 break;
3334 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003336 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003337 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3338 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003343 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003344 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003345 file, linenum, newsrv->id);
3346 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003347 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003348 file, linenum);
3349
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
3353 }
3354
3355 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003356 if (newsrv->trackit) {
3357 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003361 }
3362
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003363 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3364 newsrv->check_port = newsrv->check_addr.sin_port;
3365
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3367 newsrv->check_port = realport; /* by default */
3368 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003369 /* not yet valid, because no port was set on
3370 * the server either. We'll check if we have
3371 * a known port on the first listener.
3372 */
3373 struct listener *l;
3374 l = curproxy->listen;
3375 if (l) {
3376 int port;
3377 port = (l->addr.ss_family == AF_INET6)
3378 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3379 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3380 newsrv->check_port = port;
3381 }
3382 }
3383 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3385 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003389
3390 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 newsrv->state |= SRV_CHECKED;
3392 }
3393
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003394 if (!defsrv) {
3395 if (newsrv->state & SRV_BACKUP)
3396 curproxy->srv_bck++;
3397 else
3398 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003399
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003400 newsrv->prev_state = newsrv->state;
3401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003404 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 int facility;
3406
3407 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3408 curproxy->logfac1 = global.logfac1;
3409 curproxy->logsrv1 = global.logsrv1;
3410 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003411 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 curproxy->logfac2 = global.logfac2;
3413 curproxy->logsrv2 = global.logsrv2;
3414 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003415 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 }
3417 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003418 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419
3420 facility = get_log_facility(args[2]);
3421 if (facility < 0) {
3422 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3423 exit(1);
3424 }
3425
3426 level = 7; /* max syslog level = debug */
3427 if (*(args[3])) {
3428 level = get_log_level(args[3]);
3429 if (level < 0) {
3430 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3431 exit(1);
3432 }
3433 }
3434
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003435 minlvl = 0; /* limit syslog level to this level (emerg) */
3436 if (*(args[4])) {
3437 minlvl = get_log_level(args[4]);
3438 if (level < 0) {
3439 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3440 exit(1);
3441 }
3442 }
3443
Robert Tsai81ae1952007-12-05 10:47:29 +01003444 if (args[1][0] == '/') {
3445 logsrv.u.addr.sa_family = AF_UNIX;
3446 logsrv.u.un = *str2sun(args[1]);
3447 } else {
3448 logsrv.u.addr.sa_family = AF_INET;
3449 logsrv.u.in = *str2sa(args[1]);
3450 if (!logsrv.u.in.sin_port) {
3451 logsrv.u.in.sin_port =
3452 htons(SYSLOG_PORT);
3453 }
3454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455
3456 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003457 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 curproxy->logfac1 = facility;
3459 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003460 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 }
3462 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003463 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003464 curproxy->logfac2 = facility;
3465 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003466 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 }
3468 else {
3469 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472 }
3473 }
3474 else {
3475 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3476 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 }
3480 }
3481 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003482 int cur_arg;
3483
Willy Tarreau977b8e42006-12-29 14:19:17 +01003484 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003486
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003488 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3489 file, linenum, "source", "usesrc", "interface");
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 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003493
3494 /* we must first clear any optional default setting */
3495 curproxy->options &= ~PR_O_TPXY_MASK;
3496 free(curproxy->iface_name);
3497 curproxy->iface_name = NULL;
3498 curproxy->iface_len = 0;
3499
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 curproxy->source_addr = *str2sa(args[1]);
3501 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003502
3503 cur_arg = 2;
3504 while (*(args[cur_arg])) {
3505 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003506#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3507#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003508 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3509 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3510 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003513 }
3514#endif
3515 if (!*args[cur_arg + 1]) {
3516 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3517 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003520 }
3521
3522 if (!strcmp(args[cur_arg + 1], "client")) {
3523 curproxy->options |= PR_O_TPXY_CLI;
3524 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3525 curproxy->options |= PR_O_TPXY_CIP;
3526 } else {
3527 curproxy->options |= PR_O_TPXY_ADDR;
3528 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3529 }
3530 global.last_checks |= LSTCHK_NETADM;
3531#if !defined(CONFIG_HAP_LINUX_TPROXY)
3532 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003533#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003534#else /* no TPROXY support */
3535 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003536 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003539#endif
3540 cur_arg += 2;
3541 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003542 }
3543
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003544 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3545#ifdef SO_BINDTODEVICE
3546 if (!*args[cur_arg + 1]) {
3547 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3548 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003551 }
3552 if (curproxy->iface_name)
3553 free(curproxy->iface_name);
3554
3555 curproxy->iface_name = strdup(args[cur_arg + 1]);
3556 curproxy->iface_len = strlen(curproxy->iface_name);
3557 global.last_checks |= LSTCHK_NETADM;
3558#else
3559 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3560 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003563#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003564 cur_arg += 2;
3565 continue;
3566 }
3567 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3568 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003573 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3574 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3575 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3580 regex_t *preg;
3581 if (curproxy == &defproxy) {
3582 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003586 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003588
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 if (*(args[1]) == 0 || *(args[2]) == 0) {
3590 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3591 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 }
3595
3596 preg = calloc(1, sizeof(regex_t));
3597 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3598 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 }
3602
3603 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3604 if (err) {
3605 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3606 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003609 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 }
3611 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3612 regex_t *preg;
3613 if (curproxy == &defproxy) {
3614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003618 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003620
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 if (*(args[1]) == 0) {
3622 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 }
3626
3627 preg = calloc(1, sizeof(regex_t));
3628 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3629 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
3633
3634 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003635 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 }
3637 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3638 regex_t *preg;
3639 if (curproxy == &defproxy) {
3640 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003644 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003646
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 if (*(args[1]) == 0) {
3648 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
3652
3653 preg = calloc(1, sizeof(regex_t));
3654 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3655 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 }
3659
3660 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003661 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 }
3663 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3664 regex_t *preg;
3665 if (curproxy == &defproxy) {
3666 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003667 err_code |= ERR_ALERT | ERR_FATAL;
3668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003669 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003670 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003672
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 if (*(args[1]) == 0) {
3674 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 }
3678
3679 preg = calloc(1, sizeof(regex_t));
3680 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3681 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 }
3685
3686 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003687 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
3689 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3690 regex_t *preg;
3691 if (curproxy == &defproxy) {
3692 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003696 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003698
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 if (*(args[1]) == 0) {
3700 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003703 }
3704
3705 preg = calloc(1, sizeof(regex_t));
3706 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3707 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 }
3711
3712 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003713 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003715 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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 Tarreaub8750a82006-09-03 09:56:00 +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 Tarreau977b8e42006-12-29 14:19:17 +01003724
Willy Tarreaub8750a82006-09-03 09:56:00 +02003725 if (*(args[1]) == 0) {
3726 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003729 }
3730
3731 preg = calloc(1, sizeof(regex_t));
3732 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3733 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003736 }
3737
3738 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003739 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003740 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003741 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3742 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003743 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003747 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003748 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003750
Willy Tarreau977b8e42006-12-29 14:19:17 +01003751 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003752 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3753 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003756 }
3757
3758 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003759 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003760 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003763 }
3764
3765 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003766 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003767 }
3768 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3769 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003770 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003771 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003775 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003777
Willy Tarreau977b8e42006-12-29 14:19:17 +01003778 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003779 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3780 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003783 }
3784
3785 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003786 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003787 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003790 }
3791
3792 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003793 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3796 regex_t *preg;
3797 if (curproxy == &defproxy) {
3798 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003802 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003804
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 if (*(args[1]) == 0 || *(args[2]) == 0) {
3806 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3807 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
3811
3812 preg = calloc(1, sizeof(regex_t));
3813 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3814 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818
3819 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3820 if (err) {
3821 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3822 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003826 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 }
3828 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3829 regex_t *preg;
3830 if (curproxy == &defproxy) {
3831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003835 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003837
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 if (*(args[1]) == 0) {
3839 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
3843
3844 preg = calloc(1, sizeof(regex_t));
3845 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3846 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 }
3850
3851 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003852 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 }
3854 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3855 regex_t *preg;
3856 if (curproxy == &defproxy) {
3857 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003861 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003863
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 if (*(args[1]) == 0) {
3865 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869
3870 preg = calloc(1, sizeof(regex_t));
3871 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3872 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
3876
3877 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003878 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 }
3880 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3881 regex_t *preg;
3882 if (curproxy == &defproxy) {
3883 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003887 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003889
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 if (*(args[1]) == 0) {
3891 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 }
3895
3896 preg = calloc(1, sizeof(regex_t));
3897 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3898 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 }
3902
3903 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003904 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 }
3906 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3907 regex_t *preg;
3908 if (curproxy == &defproxy) {
3909 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003913 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003915
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916 if (*(args[1]) == 0) {
3917 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003920 }
3921
3922 preg = calloc(1, sizeof(regex_t));
3923 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3924 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 }
3928
3929 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003930 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003932 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3933 regex_t *preg;
3934 if (curproxy == &defproxy) {
3935 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003938 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003939 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003941
Willy Tarreaub8750a82006-09-03 09:56:00 +02003942 if (*(args[1]) == 0) {
3943 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003946 }
3947
3948 preg = calloc(1, sizeof(regex_t));
3949 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3950 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003953 }
3954
3955 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003956 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003959 struct wordlist *wl;
3960
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 if (curproxy == &defproxy) {
3962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003966 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 if (*(args[1]) == 0) {
3970 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003974
3975 wl = calloc(1, sizeof(*wl));
3976 wl->s = strdup(args[1]);
3977 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003978 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 }
3980 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3981 regex_t *preg;
3982
3983 if (*(args[1]) == 0 || *(args[2]) == 0) {
3984 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3985 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003989 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003991
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 preg = calloc(1, sizeof(regex_t));
3993 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3994 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 }
3998
3999 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
4000 if (err) {
4001 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4002 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 }
Willy Tarreau61d18892009-03-31 10:49:21 +02004006 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 }
4008 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
4009 regex_t *preg;
4010 if (curproxy == &defproxy) {
4011 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004015 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004016 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004017
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 if (*(args[1]) == 0) {
4019 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 }
4023
4024 preg = calloc(1, sizeof(regex_t));
4025 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4026 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029 }
4030
4031 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4032 if (err) {
4033 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4034 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 }
4038 }
4039 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
4040 regex_t *preg;
4041 if (curproxy == &defproxy) {
4042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004046 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004048
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 if (*(args[1]) == 0) {
4050 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 }
4054
4055 preg = calloc(1, sizeof(regex_t));
4056 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4057 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 }
4061
4062 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4063 if (err) {
4064 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4065 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 }
4069 }
4070 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
4071 regex_t *preg;
4072 if (curproxy == &defproxy) {
4073 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004077 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004079
4080 if (*(args[1]) == 0 || *(args[2]) == 0) {
4081 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4082 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004085 }
4086
4087 preg = calloc(1, sizeof(regex_t));
4088 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4089 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 }
4093
4094 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
4095 if (err) {
4096 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4097 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 }
4101 }
4102 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
4103 regex_t *preg;
4104 if (curproxy == &defproxy) {
4105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004109 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004111
Willy Tarreaubaaee002006-06-26 02:48:02 +02004112 if (*(args[1]) == 0) {
4113 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 }
4117
4118 preg = calloc(1, sizeof(regex_t));
4119 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4120 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004123 }
4124
4125 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4126 if (err) {
4127 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4128 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 }
4132 }
4133 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
4134 regex_t *preg;
4135 if (curproxy == &defproxy) {
4136 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004140 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004141 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004142
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 if (*(args[1]) == 0) {
4144 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147 }
4148
4149 preg = calloc(1, sizeof(regex_t));
4150 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4151 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
4155
4156 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4157 if (err) {
4158 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4159 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 }
4163 }
4164 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004165 struct wordlist *wl;
4166
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 if (curproxy == &defproxy) {
4168 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004172 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 if (*(args[1]) == 0) {
4176 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 }
4180
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004181 wl = calloc(1, sizeof(*wl));
4182 wl->s = strdup(args[1]);
4183 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 }
4185 else if (!strcmp(args[0], "errorloc") ||
4186 !strcmp(args[0], "errorloc302") ||
4187 !strcmp(args[0], "errorloc303")) { /* error location */
4188 int errnum, errlen;
4189 char *err;
4190
Willy Tarreau977b8e42006-12-29 14:19:17 +01004191 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004193
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004195 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 }
4199
4200 errnum = atol(args[1]);
4201 if (!strcmp(args[0], "errorloc303")) {
4202 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4203 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4204 } else {
4205 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4206 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4207 }
4208
Willy Tarreau0f772532006-12-23 20:51:41 +01004209 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4210 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004211 chunk_destroy(&curproxy->errmsg[rc]);
4212 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004213 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004216
4217 if (rc >= HTTP_ERR_SIZE) {
4218 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4219 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 free(err);
4221 }
4222 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004223 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4224 int errnum, errlen, fd;
4225 char *err;
4226 struct stat stat;
4227
4228 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004229 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004230
4231 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004232 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004235 }
4236
4237 fd = open(args[2], O_RDONLY);
4238 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4239 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4240 file, linenum, args[2], args[1]);
4241 if (fd >= 0)
4242 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004245 }
4246
Willy Tarreau27a674e2009-08-17 07:23:33 +02004247 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004248 errlen = stat.st_size;
4249 } else {
4250 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004251 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004252 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004253 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004254 }
4255
4256 err = malloc(errlen); /* malloc() must succeed during parsing */
4257 errnum = read(fd, err, errlen);
4258 if (errnum != errlen) {
4259 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4260 file, linenum, args[2], args[1]);
4261 close(fd);
4262 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004265 }
4266 close(fd);
4267
4268 errnum = atol(args[1]);
4269 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4270 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004271 chunk_destroy(&curproxy->errmsg[rc]);
4272 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004273 break;
4274 }
4275 }
4276
4277 if (rc >= HTTP_ERR_SIZE) {
4278 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4279 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004281 free(err);
4282 }
4283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004285 struct cfg_kw_list *kwl;
4286 int index;
4287
4288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4290 if (kwl->kw[index].section != CFG_LISTEN)
4291 continue;
4292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4293 /* prepare error message just in case */
4294 snprintf(trash, sizeof(trash),
4295 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004296 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4297 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004298 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004301 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004302 else if (rc > 0) {
4303 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_WARN;
4305 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004306 }
Willy Tarreau93893792009-07-23 13:19:11 +02004307 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004308 }
4309 }
4310 }
4311
Willy Tarreau6daf3432008-01-22 16:44:08 +01004312 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 }
Willy Tarreau93893792009-07-23 13:19:11 +02004316 out:
4317 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004318}
4319
4320
4321/*
4322 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004323 * Returns the error code, 0 if OK, or any combination of :
4324 * - ERR_ABORT: must abort ASAP
4325 * - ERR_FATAL: we can continue parsing but not start the service
4326 * - ERR_WARN: a warning has been emitted
4327 * - ERR_ALERT: an alert has been emitted
4328 * Only the two first ones can stop processing, the two others are just
4329 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004331int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004333 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334 FILE *f;
4335 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004337 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 if ((f=fopen(file,"r")) == NULL)
4340 return -1;
4341
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004342 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004343 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004344 char *end;
4345 char *args[MAX_LINE_ARGS + 1];
4346 char *line = thisline;
4347
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348 linenum++;
4349
4350 end = line + strlen(line);
4351
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004352 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4353 /* Check if we reached the limit and the last char is not \n.
4354 * Watch out for the last line without the terminating '\n'!
4355 */
4356 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004357 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004358 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004359 }
4360
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004362 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 line++;
4364
4365 arg = 0;
4366 args[arg] = line;
4367
4368 while (*line && arg < MAX_LINE_ARGS) {
4369 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4370 * C equivalent value. Other combinations left unchanged (eg: \1).
4371 */
4372 if (*line == '\\') {
4373 int skip = 0;
4374 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4375 *line = line[1];
4376 skip = 1;
4377 }
4378 else if (line[1] == 'r') {
4379 *line = '\r';
4380 skip = 1;
4381 }
4382 else if (line[1] == 'n') {
4383 *line = '\n';
4384 skip = 1;
4385 }
4386 else if (line[1] == 't') {
4387 *line = '\t';
4388 skip = 1;
4389 }
4390 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004391 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 unsigned char hex1, hex2;
4393 hex1 = toupper(line[2]) - '0';
4394 hex2 = toupper(line[3]) - '0';
4395 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4396 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4397 *line = (hex1<<4) + hex2;
4398 skip = 3;
4399 }
4400 else {
4401 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 }
4404 }
4405 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004406 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 end -= skip;
4408 }
4409 line++;
4410 }
4411 else if (*line == '#' || *line == '\n' || *line == '\r') {
4412 /* end of string, end of loop */
4413 *line = 0;
4414 break;
4415 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004416 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004418 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004419 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 line++;
4421 args[++arg] = line;
4422 }
4423 else {
4424 line++;
4425 }
4426 }
4427
4428 /* empty line */
4429 if (!**args)
4430 continue;
4431
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004432 if (*line) {
4433 /* we had to stop due to too many args.
4434 * Let's terminate the string, print the offending part then cut the
4435 * last arg.
4436 */
4437 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4438 line++;
4439 *line = '\0';
4440
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004441 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004442 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 args[arg] = line;
4445 }
4446
Willy Tarreau540abe42007-05-02 20:50:16 +02004447 /* zero out remaining args and ensure that at least one entry
4448 * is zeroed out.
4449 */
4450 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 args[arg] = line;
4452 }
4453
Willy Tarreau3842f002009-06-14 11:39:52 +02004454 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004455 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004456 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004457 for (arg=0; *args[arg+1]; arg++)
4458 args[arg] = args[arg+1]; // shift args after inversion
4459 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004460 else if (!strcmp(args[0], "default")) {
4461 kwm = KWM_DEF;
4462 for (arg=0; *args[arg+1]; arg++)
4463 args[arg] = args[arg+1]; // shift args after inversion
4464 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004465
Willy Tarreau3842f002009-06-14 11:39:52 +02004466 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4467 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004468 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004469 }
4470
Willy Tarreau977b8e42006-12-29 14:19:17 +01004471 if (!strcmp(args[0], "listen") ||
4472 !strcmp(args[0], "frontend") ||
4473 !strcmp(args[0], "backend") ||
4474 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004475 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004477 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004478 cursection = strdup(args[0]);
4479 }
4480 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004482 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004483 cursection = strdup(args[0]);
4484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 /* else it's a section keyword */
4486
4487 switch (confsect) {
4488 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 break;
4491 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004492 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 break;
4494 default:
4495 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004498
4499 if (err_code & ERR_ABORT)
4500 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004502 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004503 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004505 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004506}
4507
Willy Tarreaubb925012009-07-23 13:36:36 +02004508/*
4509 * Returns the error code, 0 if OK, or any combination of :
4510 * - ERR_ABORT: must abort ASAP
4511 * - ERR_FATAL: we can continue parsing but not start the service
4512 * - ERR_WARN: a warning has been emitted
4513 * - ERR_ALERT: an alert has been emitted
4514 * Only the two first ones can stop processing, the two others are just
4515 * indicators.
4516 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004517int check_config_validity()
4518{
4519 int cfgerr = 0;
4520 struct proxy *curproxy = NULL;
4521 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004522 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004523 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524
4525 /*
4526 * Now, check for the integrity of all that we have collected.
4527 */
4528
4529 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004530 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004532 /* first, we will invert the proxy list order */
4533 curproxy = NULL;
4534 while (proxy) {
4535 struct proxy *next;
4536
4537 next = proxy->next;
4538 proxy->next = curproxy;
4539 curproxy = proxy;
4540 if (!next)
4541 break;
4542 proxy = next;
4543 }
4544
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004546 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549 }
4550
4551 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004552 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004553 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004554 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004555 unsigned int next_id;
4556
4557 if (!curproxy->uuid) {
4558 /* proxy ID not set, use automatic numbering with first
4559 * spare entry starting with next_pxid.
4560 */
4561 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4562 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4563 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4564 next_pxid++;
4565 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004566
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004568 /* ensure we don't keep listeners uselessly bound */
4569 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004570 curproxy = curproxy->next;
4571 continue;
4572 }
4573
Willy Tarreauff01a212009-03-15 13:46:16 +01004574 switch (curproxy->mode) {
4575 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004576 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004577 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004578 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4579 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004580 cfgerr++;
4581 }
4582
4583 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004584 Warning("config : servers will be ignored for %s '%s'.\n",
4585 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004586 break;
4587
4588 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004589 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004590 break;
4591
4592 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004593 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004594 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004595 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4596 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004597 cfgerr++;
4598 }
4599 break;
4600 }
4601
4602 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004603 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4604 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 cfgerr++;
4606 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004607
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004608 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004609 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004610 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004611 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4612 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004613 cfgerr++;
4614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004615#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004616 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004617 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4618 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004619 cfgerr++;
4620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004622 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004623 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4624 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004625 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004626 }
4627 }
4628 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4629 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4630 /* If no LB algo is set in a backend, and we're not in
4631 * transparent mode, dispatch mode nor proxy mode, we
4632 * want to use balance roundrobin by default.
4633 */
4634 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4635 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636 }
4637 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004638
Willy Tarreau82936582007-11-30 15:20:09 +01004639 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4640 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004641 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4642 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004643 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004644 }
4645
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004646 /* if a default backend was specified, let's find it */
4647 if (curproxy->defbe.name) {
4648 struct proxy *target;
4649
Alex Williams96532db2009-11-01 21:27:13 -05004650 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004651 if (!target) {
4652 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4653 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004654 cfgerr++;
4655 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004656 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4657 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004658 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004659 } else {
4660 free(curproxy->defbe.name);
4661 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004662 /* we force the backend to be present on at least all of
4663 * the frontend's processes.
4664 */
4665 target->bind_proc = curproxy->bind_proc ?
4666 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 }
4668 }
4669
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004670 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004671 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4672 /* map jump target for ACT_SETBE in req_rep chain */
4673 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004674 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004675 struct proxy *target;
4676
Willy Tarreaua496b602006-12-17 23:15:24 +01004677 if (exp->action != ACT_SETBE)
4678 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004679
Alex Williams96532db2009-11-01 21:27:13 -05004680 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004681 if (!target) {
4682 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4683 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004684 cfgerr++;
4685 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004686 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4687 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004688 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004689 } else {
4690 free((void *)exp->replace);
4691 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004692 /* we force the backend to be present on at least all of
4693 * the frontend's processes.
4694 */
4695 target->bind_proc = curproxy->bind_proc ?
4696 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004697 }
4698 }
4699 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004700
4701 /* find the target proxy for 'use_backend' rules */
4702 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004703 struct proxy *target;
4704
Alex Williams96532db2009-11-01 21:27:13 -05004705 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004706
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004707 if (!target) {
4708 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4709 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004710 cfgerr++;
4711 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004712 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4713 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004714 cfgerr++;
4715 } else {
4716 free((void *)rule->be.name);
4717 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004718 /* we force the backend to be present on at least all of
4719 * the frontend's processes.
4720 */
4721 target->bind_proc = curproxy->bind_proc ?
4722 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004723 }
4724 }
4725
Emeric Brunb982a3d2010-01-04 15:45:53 +01004726 /* find the target table for 'stick' rules */
4727 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4728 struct proxy *target;
4729
Emeric Brun1d33b292010-01-04 15:47:17 +01004730 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4731 if (mrule->flags & STK_IS_STORE)
4732 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4733
Emeric Brunb982a3d2010-01-04 15:45:53 +01004734 if (mrule->table.name)
4735 target = findproxy(mrule->table.name, PR_CAP_BE);
4736 else
4737 target = curproxy;
4738
4739 if (!target) {
4740 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4741 curproxy->id, mrule->table.name);
4742 cfgerr++;
4743 }
4744 else if (target->table.size == 0) {
4745 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4746 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4747 cfgerr++;
4748 }
4749 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4750 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4751 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4752 cfgerr++;
4753 }
4754 else {
4755 free((void *)mrule->table.name);
4756 mrule->table.t = &(target->table);
4757 }
4758 }
4759
4760 /* find the target table for 'store response' rules */
4761 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4762 struct proxy *target;
4763
Emeric Brun1d33b292010-01-04 15:47:17 +01004764 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4765
Emeric Brunb982a3d2010-01-04 15:45:53 +01004766 if (mrule->table.name)
4767 target = findproxy(mrule->table.name, PR_CAP_BE);
4768 else
4769 target = curproxy;
4770
4771 if (!target) {
4772 Alert("Proxy '%s': unable to find store table '%s'.\n",
4773 curproxy->id, mrule->table.name);
4774 cfgerr++;
4775 }
4776 else if (target->table.size == 0) {
4777 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4778 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4779 cfgerr++;
4780 }
4781 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4782 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4783 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4784 cfgerr++;
4785 }
4786 else {
4787 free((void *)mrule->table.name);
4788 mrule->table.t = &(target->table);
4789 }
4790 }
4791
Willy Tarreau2738a142006-07-08 17:28:09 +02004792 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004793 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004794 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004795 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004796 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004797 " | While not properly invalid, you will certainly encounter various problems\n"
4798 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004799 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004800 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004801 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004802 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004803
Willy Tarreau1fa31262007-12-03 00:36:16 +01004804 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4805 * We must still support older configurations, so let's find out whether those
4806 * parameters have been set or must be copied from contimeouts.
4807 */
4808 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004809 if (!curproxy->timeout.tarpit ||
4810 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004811 /* tarpit timeout not set. We search in the following order:
4812 * default.tarpit, curr.connect, default.connect.
4813 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004814 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004815 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004816 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004817 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004818 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004819 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004820 }
4821 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004822 (!curproxy->timeout.queue ||
4823 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004824 /* queue timeout not set. We search in the following order:
4825 * default.queue, curr.connect, default.connect.
4826 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004827 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004828 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004829 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004830 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004831 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004832 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004833 }
4834 }
4835
Willy Tarreauf3c69202006-07-09 16:42:34 +02004836 if (curproxy->options & PR_O_SSL3_CHK) {
4837 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4838 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4839 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4840 }
4841
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004842 /* The small pools required for the capture lists */
4843 if (curproxy->nb_req_cap)
4844 curproxy->req_cap_pool = create_pool("ptrcap",
4845 curproxy->nb_req_cap * sizeof(char *),
4846 MEM_F_SHARED);
4847 if (curproxy->nb_rsp_cap)
4848 curproxy->rsp_cap_pool = create_pool("ptrcap",
4849 curproxy->nb_rsp_cap * sizeof(char *),
4850 MEM_F_SHARED);
4851
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004852 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4853 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4854 MEM_F_SHARED);
4855
Willy Tarreau86034312006-12-29 00:10:33 +01004856 /* for backwards compatibility with "listen" instances, if
4857 * fullconn is not set but maxconn is set, then maxconn
4858 * is used.
4859 */
4860 if (!curproxy->fullconn)
4861 curproxy->fullconn = curproxy->maxconn;
4862
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 /* first, we will invert the servers list order */
4864 newsrv = NULL;
4865 while (curproxy->srv) {
4866 struct server *next;
4867
4868 next = curproxy->srv->next;
4869 curproxy->srv->next = newsrv;
4870 newsrv = curproxy->srv;
4871 if (!next)
4872 break;
4873 curproxy->srv = next;
4874 }
4875
Willy Tarreau20697042007-11-15 23:26:18 +01004876 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004877 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004879 /* We have to initialize the server lookup mechanism depending
4880 * on what LB algorithm was choosen.
4881 */
4882
4883 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4884 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4885 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004886 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4887 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4888 init_server_map(curproxy);
4889 } else {
4890 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4891 fwrr_init_server_groups(curproxy);
4892 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004893 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004894
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004895 case BE_LB_KIND_LC:
4896 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004897 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004898 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004899
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004900 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004901 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4902 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4903 chash_init_server_tree(curproxy);
4904 } else {
4905 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4906 init_server_map(curproxy);
4907 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004908 break;
4909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910
4911 if (curproxy->options & PR_O_LOGASAP)
4912 curproxy->to_log &= ~LW_BYTES;
4913
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004914 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4915 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4916 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4917 proxy_type_str(curproxy), curproxy->id);
4918 err_code |= ERR_WARN;
4919 }
4920
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004922 * ensure that we're not cross-dressing a TCP server into HTTP.
4923 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004924 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004925 newsrv = curproxy->srv;
4926 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004927 if (!newsrv->puid) {
4928 /* server ID not set, use automatic numbering with first
4929 * spare entry starting with next_svid.
4930 */
4931 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4932 newsrv->conf.id.key = newsrv->puid = next_id;
4933 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4934 next_id++;
4935 }
4936
Willy Tarreau21d2af32008-02-14 20:25:24 +01004937 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004938 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4939 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004940 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004941 }
4942 newsrv = newsrv->next;
4943 }
4944
4945 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 * If this server supports a maxconn parameter, it needs a dedicated
4947 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004948 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 */
4950 newsrv = curproxy->srv;
4951 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004952 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 /* Only 'minconn' was specified, or it was higher than or equal
4954 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4955 * this will avoid further useless expensive computations.
4956 */
4957 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004958 } else if (newsrv->maxconn && !newsrv->minconn) {
4959 /* minconn was not specified, so we set it to maxconn */
4960 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004961 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004962 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4963 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004964 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004967 if (newsrv->trackit) {
4968 struct proxy *px;
4969 struct server *srv;
4970 char *pname, *sname;
4971
4972 pname = newsrv->trackit;
4973 sname = strrchr(pname, '/');
4974
4975 if (sname)
4976 *sname++ = '\0';
4977 else {
4978 sname = pname;
4979 pname = NULL;
4980 }
4981
4982 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004983 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004984 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004985 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4986 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004987 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004988 cfgerr++;
4989 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004990 }
4991 } else
4992 px = curproxy;
4993
4994 srv = findserver(px, sname);
4995 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004996 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4997 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004998 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004999 cfgerr++;
5000 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005001 }
5002
5003 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005004 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005005 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005006 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005007 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005008 cfgerr++;
5009 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005010 }
5011
5012 if (curproxy != px &&
5013 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005014 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005015 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005016 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005017 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005018 cfgerr++;
5019 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005020 }
5021
5022 newsrv->tracked = srv;
5023 newsrv->tracknext = srv->tracknext;
5024 srv->tracknext = newsrv;
5025
5026 free(newsrv->trackit);
5027 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005028 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 newsrv = newsrv->next;
5030 }
5031
Willy Tarreauc1a21672009-08-16 22:37:44 +02005032 if (curproxy->cap & PR_CAP_FE) {
5033 if (curproxy->tcp_req.inspect_delay ||
5034 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5035 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5036
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005037 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005038 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005039 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005040 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005041
5042 /* both TCP and HTTP must check switching rules */
5043 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5044 }
5045
5046 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005047 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005048 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005049 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005050 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005051
Emeric Brunb982a3d2010-01-04 15:45:53 +01005052 /* init table on backend capabilities proxy */
5053 stktable_init(&curproxy->table);
5054
Willy Tarreauc1a21672009-08-16 22:37:44 +02005055 /* If the backend does requires RDP cookie persistence, we have to
5056 * enable the corresponding analyser.
5057 */
5058 if (curproxy->options2 & PR_O2_RDPC_PRST)
5059 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5060 }
5061
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005062 listener = NULL;
5063 while (curproxy->listen) {
5064 struct listener *next;
5065
5066 next = curproxy->listen->next;
5067 curproxy->listen->next = listener;
5068 listener = curproxy->listen;
5069
5070 if (!next)
5071 break;
5072
5073 curproxy->listen = next;
5074 }
5075
Willy Tarreaue6b98942007-10-29 01:09:36 +01005076 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005077 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005078 listener = curproxy->listen;
5079 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005080 if (!listener->luid) {
5081 /* listener ID not set, use automatic numbering with first
5082 * spare entry starting with next_luid.
5083 */
5084 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5085 listener->conf.id.key = listener->luid = next_id;
5086 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
5087 next_id++;
5088 }
5089
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005090 /* enable separate counters */
5091 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5092 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5093 if (!listener->name) {
5094 sprintf(trash, "sock-%d", listener->luid);
5095 listener->name = strdup(trash);
5096 }
5097 }
5098
Willy Tarreaue6b98942007-10-29 01:09:36 +01005099 if (curproxy->options & PR_O_TCP_NOLING)
5100 listener->options |= LI_O_NOLINGER;
5101 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005102 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005103 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005104 listener->accept = event_accept;
5105 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005106 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005107 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005108
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005109 /* smart accept mode is automatic in HTTP mode */
5110 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5111 (curproxy->mode == PR_MODE_HTTP &&
5112 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5113 listener->options |= LI_O_NOQUICKACK;
5114
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005115 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005116 listener = listener->next;
5117 }
5118
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 curproxy = curproxy->next;
5120 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005121
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005122 /*
5123 * Recount currently required checks.
5124 */
5125
5126 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5127 int optnum;
5128
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005129 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5130 if (curproxy->options & cfg_opts[optnum].val)
5131 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005132
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005133 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5134 if (curproxy->options2 & cfg_opts2[optnum].val)
5135 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005136 }
5137
Willy Tarreaubb925012009-07-23 13:36:36 +02005138 if (cfgerr > 0)
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 out:
5141 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142}
5143
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005144/*
5145 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5146 * parsing sessions.
5147 */
5148void cfg_register_keywords(struct cfg_kw_list *kwl)
5149{
5150 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5151}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005153/*
5154 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5155 */
5156void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5157{
5158 LIST_DEL(&kwl->list);
5159 LIST_INIT(&kwl->list);
5160}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161
5162/*
5163 * Local variables:
5164 * c-indent-level: 8
5165 * c-basic-offset: 8
5166 * End:
5167 */