blob: 39a79f2f7b49fd556e777557b4e57597d6de8472 [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 Tarreau66aa61f2009-01-18 21:44:07 +0100150 { NULL, 0, 0, 0 }
151};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200152
Willy Tarreau6daf3432008-01-22 16:44:08 +0100153static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
155int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100156int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200157
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200158/* List head of all known configuration keywords */
159static struct cfg_kw_list cfg_keywords = {
160 .list = LIST_HEAD_INIT(cfg_keywords.list)
161};
162
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163/*
164 * converts <str> to a list of listeners which are dynamically allocated.
165 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
166 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
167 * - <port> is a numerical port from 1 to 65535 ;
168 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
169 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200170 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173{
174 struct listener *l;
175 char *c, *next, *range, *dupstr;
176 int port, end;
177
178 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200179
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180 while (next && *next) {
181 struct sockaddr_storage ss;
182
183 str = next;
184 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100185 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 *next++ = 0;
187 }
188
189 /* 2) look for the addr/port delimiter, it's the last colon. */
190 if ((range = strrchr(str, ':')) == NULL) {
191 Alert("Missing port number: '%s'\n", str);
192 goto fail;
193 }
194
195 *range++ = 0;
196
197 if (strrchr(str, ':') != NULL) {
198 /* IPv6 address contains ':' */
199 memset(&ss, 0, sizeof(ss));
200 ss.ss_family = AF_INET6;
201
202 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
203 Alert("Invalid server address: '%s'\n", str);
204 goto fail;
205 }
206 }
207 else {
208 memset(&ss, 0, sizeof(ss));
209 ss.ss_family = AF_INET;
210
211 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
212 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
213 }
214 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
215 struct hostent *he;
216
217 if ((he = gethostbyname(str)) == NULL) {
218 Alert("Invalid server name: '%s'\n", str);
219 goto fail;
220 }
221 else
222 ((struct sockaddr_in *)&ss)->sin_addr =
223 *(struct in_addr *) *(he->h_addr_list);
224 }
225 }
226
227 /* 3) look for the port-end delimiter */
228 if ((c = strchr(range, '-')) != NULL) {
229 *c++ = 0;
230 end = atol(c);
231 }
232 else {
233 end = atol(range);
234 }
235
236 port = atol(range);
237
238 if (port < 1 || port > 65535) {
239 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
240 goto fail;
241 }
242
243 if (end < 1 || end > 65535) {
244 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
245 goto fail;
246 }
247
248 for (; port <= end; port++) {
249 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200250 l->next = curproxy->listen;
251 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
253 l->fd = -1;
254 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100255 l->state = LI_INIT;
256
257 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100259 tcpv6_add_listener(l);
260 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100262 tcpv4_add_listener(l);
263 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200264
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 } /* end for(port) */
267 } /* end while(next) */
268 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 fail:
271 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200272 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273}
274
Willy Tarreau977b8e42006-12-29 14:19:17 +0100275/*
276 * Sends a warning if proxy <proxy> does not have at least one of the
277 * capabilities in <cap>. An optionnal <hint> may be added at the end
278 * of the warning to help the user. Returns 1 if a warning was emitted
279 * or 0 if the condition is valid.
280 */
281int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
282{
283 char *msg;
284
285 switch (cap) {
286 case PR_CAP_BE: msg = "no backend"; break;
287 case PR_CAP_FE: msg = "no frontend"; break;
288 case PR_CAP_RS: msg = "no ruleset"; break;
289 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
290 default: msg = "not enough"; break;
291 }
292
293 if (!(proxy->cap & cap)) {
294 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100295 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100296 return 1;
297 }
298 return 0;
299}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300
Willy Tarreau61d18892009-03-31 10:49:21 +0200301/* Report a warning if a rule is placed after a 'block' rule.
302 * Return 1 if the warning has been emitted, otherwise 0.
303 */
304int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
305{
306 if (!LIST_ISEMPTY(&proxy->block_cond)) {
307 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
308 file, line, arg);
309 return 1;
310 }
311 return 0;
312}
313
314/* Report a warning if a rule is placed after a reqrewrite rule.
315 * Return 1 if the warning has been emitted, otherwise 0.
316 */
317int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
318{
319 if (proxy->req_exp) {
320 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
321 file, line, arg);
322 return 1;
323 }
324 return 0;
325}
326
327/* Report a warning if a rule is placed after a reqadd rule.
328 * Return 1 if the warning has been emitted, otherwise 0.
329 */
330int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
331{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100332 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200333 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
334 file, line, arg);
335 return 1;
336 }
337 return 0;
338}
339
340/* Report a warning if a rule is placed after a redirect rule.
341 * Return 1 if the warning has been emitted, otherwise 0.
342 */
343int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
344{
345 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
346 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
347 file, line, arg);
348 return 1;
349 }
350 return 0;
351}
352
353/* Report a warning if a rule is placed after a 'use_backend' rule.
354 * Return 1 if the warning has been emitted, otherwise 0.
355 */
356int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
357{
358 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
359 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
360 file, line, arg);
361 return 1;
362 }
363 return 0;
364}
365
366/* report a warning if a block rule is dangerously placed */
367int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
368{
369 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
370 warnif_rule_after_reqadd(proxy, file, line, arg) ||
371 warnif_rule_after_redirect(proxy, file, line, arg) ||
372 warnif_rule_after_use_backend(proxy, file, line, arg);
373}
374
375/* report a warning if a reqxxx rule is dangerously placed */
376int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
377{
378 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
379 warnif_rule_after_redirect(proxy, file, line, arg) ||
380 warnif_rule_after_use_backend(proxy, file, line, arg);
381}
382
383/* report a warning if a reqadd rule is dangerously placed */
384int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
385{
386 return warnif_rule_after_redirect(proxy, file, line, arg) ||
387 warnif_rule_after_use_backend(proxy, file, line, arg);
388}
389
Willy Tarreaubaaee002006-06-26 02:48:02 +0200390/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200391 * parse a line in a <global> section. Returns the error code, 0 if OK, or
392 * any combination of :
393 * - ERR_ABORT: must abort ASAP
394 * - ERR_FATAL: we can continue parsing but not start the service
395 * - ERR_WARN: a warning has been emitted
396 * - ERR_ALERT: an alert has been emitted
397 * Only the two first ones can stop processing, the two others are just
398 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200399 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200400int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401{
Willy Tarreau058e9072009-07-20 09:30:05 +0200402 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200403
404 if (!strcmp(args[0], "global")) { /* new section */
405 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200407 }
408 else if (!strcmp(args[0], "daemon")) {
409 global.mode |= MODE_DAEMON;
410 }
411 else if (!strcmp(args[0], "debug")) {
412 global.mode |= MODE_DEBUG;
413 }
414 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100415 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200416 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200417 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100418 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200419 }
420 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100421 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200423 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100424 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200425 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100426 else if (!strcmp(args[0], "nosplice")) {
427 global.tune.options &= ~GTUNE_USE_SPLICE;
428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 else if (!strcmp(args[0], "quiet")) {
430 global.mode |= MODE_QUIET;
431 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200432 else if (!strcmp(args[0], "tune.maxpollevents")) {
433 if (global.tune.maxpollevents != 0) {
434 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200435 err_code |= ERR_ALERT;
436 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200437 }
438 if (*(args[1]) == 0) {
439 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200440 err_code |= ERR_ALERT | ERR_FATAL;
441 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200442 }
443 global.tune.maxpollevents = atol(args[1]);
444 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100445 else if (!strcmp(args[0], "tune.maxaccept")) {
446 if (global.tune.maxaccept != 0) {
447 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200448 err_code |= ERR_ALERT;
449 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100450 }
451 if (*(args[1]) == 0) {
452 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 err_code |= ERR_ALERT | ERR_FATAL;
454 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100455 }
456 global.tune.maxaccept = atol(args[1]);
457 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200458 else if (!strcmp(args[0], "tune.bufsize")) {
459 if (*(args[1]) == 0) {
460 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
461 err_code |= ERR_ALERT | ERR_FATAL;
462 goto out;
463 }
464 global.tune.bufsize = atol(args[1]);
465 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
466 global.tune.maxrewrite = global.tune.bufsize / 2;
467 }
468 else if (!strcmp(args[0], "tune.maxrewrite")) {
469 if (*(args[1]) == 0) {
470 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
471 err_code |= ERR_ALERT | ERR_FATAL;
472 goto out;
473 }
474 global.tune.maxrewrite = atol(args[1]);
475 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
476 global.tune.maxrewrite = global.tune.bufsize / 2;
477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 else if (!strcmp(args[0], "uid")) {
479 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200480 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200481 err_code |= ERR_ALERT;
482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 }
484 if (*(args[1]) == 0) {
485 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 }
489 global.uid = atol(args[1]);
490 }
491 else if (!strcmp(args[0], "gid")) {
492 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200493 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT;
495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200501 }
502 global.gid = atol(args[1]);
503 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200504 /* user/group name handling */
505 else if (!strcmp(args[0], "user")) {
506 struct passwd *ha_user;
507 if (global.uid != 0) {
508 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200509 err_code |= ERR_ALERT;
510 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200511 }
512 errno = 0;
513 ha_user = getpwnam(args[1]);
514 if (ha_user != NULL) {
515 global.uid = (int)ha_user->pw_uid;
516 }
517 else {
518 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 +0200519 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200520 }
521 }
522 else if (!strcmp(args[0], "group")) {
523 struct group *ha_group;
524 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200525 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200526 err_code |= ERR_ALERT;
527 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200528 }
529 errno = 0;
530 ha_group = getgrnam(args[1]);
531 if (ha_group != NULL) {
532 global.gid = (int)ha_group->gr_gid;
533 }
534 else {
535 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 +0200536 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200537 }
538 }
539 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 else if (!strcmp(args[0], "nbproc")) {
541 if (global.nbproc != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 err_code |= ERR_ALERT;
544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 }
551 global.nbproc = atol(args[1]);
552 }
553 else if (!strcmp(args[0], "maxconn")) {
554 if (global.maxconn != 0) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200556 err_code |= ERR_ALERT;
557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563 }
564 global.maxconn = atol(args[1]);
565#ifdef SYSTEM_MAXCONN
566 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
567 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);
568 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200569 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570 }
571#endif /* SYSTEM_MAXCONN */
572 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100573 else if (!strcmp(args[0], "maxpipes")) {
574 if (global.maxpipes != 0) {
575 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200576 err_code |= ERR_ALERT;
577 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100578 }
579 if (*(args[1]) == 0) {
580 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200581 err_code |= ERR_ALERT | ERR_FATAL;
582 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100583 }
584 global.maxpipes = atol(args[1]);
585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 else if (!strcmp(args[0], "ulimit-n")) {
587 if (global.rlimit_nofile != 0) {
588 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200589 err_code |= ERR_ALERT;
590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 }
592 if (*(args[1]) == 0) {
593 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200594 err_code |= ERR_ALERT | ERR_FATAL;
595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596 }
597 global.rlimit_nofile = atol(args[1]);
598 }
599 else if (!strcmp(args[0], "chroot")) {
600 if (global.chroot != NULL) {
601 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200602 err_code |= ERR_ALERT;
603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 }
605 if (*(args[1]) == 0) {
606 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 }
610 global.chroot = strdup(args[1]);
611 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200612 else if (!strcmp(args[0], "description")) {
613 int i, len=0;
614 char *d;
615
616 if (!*args[1]) {
617 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
618 file, linenum, args[0]);
619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
621 }
622
623 for(i=1; *args[i]; i++)
624 len += strlen(args[i])+1;
625
626 if (global.desc)
627 free(global.desc);
628
629 global.desc = d = (char *)calloc(1, len);
630
631 d += sprintf(d, "%s", args[1]);
632 for(i=2; *args[i]; i++)
633 d += sprintf(d, " %s", args[i]);
634 }
635 else if (!strcmp(args[0], "node")) {
636 int i;
637 char c;
638
639 for (i=0; args[1][i]; i++) {
640 c = args[1][i];
641 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
642 break;
643 }
644
645 if (!i || args[1][i]) {
646 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
647 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
648 file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652
653 if (global.node)
654 free(global.node);
655
656 global.node = strdup(args[1]);
657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 else if (!strcmp(args[0], "pidfile")) {
659 if (global.pidfile != NULL) {
660 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200661 err_code |= ERR_ALERT;
662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 }
664 if (*(args[1]) == 0) {
665 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT | ERR_FATAL;
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 }
669 global.pidfile = strdup(args[1]);
670 }
671 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100672 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200673 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674
675 if (*(args[1]) == 0 || *(args[2]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 }
680
681 facility = get_log_facility(args[2]);
682 if (facility < 0) {
683 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200684 err_code |= ERR_ALERT | ERR_FATAL;
685 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200686 }
687
688 level = 7; /* max syslog level = debug */
689 if (*(args[3])) {
690 level = get_log_level(args[3]);
691 if (level < 0) {
692 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 }
696 }
697
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200698 minlvl = 0; /* limit syslog level to this level (emerg) */
699 if (*(args[4])) {
700 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200702 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200703 err_code |= ERR_ALERT | ERR_FATAL;
704 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200705 }
706 }
707
Robert Tsai81ae1952007-12-05 10:47:29 +0100708 if (args[1][0] == '/') {
709 logsrv.u.addr.sa_family = AF_UNIX;
710 logsrv.u.un = *str2sun(args[1]);
711 } else {
712 logsrv.u.addr.sa_family = AF_INET;
713 logsrv.u.in = *str2sa(args[1]);
714 if (!logsrv.u.in.sin_port)
715 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717
718 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100719 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 global.logfac1 = facility;
721 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200722 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 }
724 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100725 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 global.logfac2 = facility;
727 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200728 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
730 else {
731 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200734 }
735 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
736 if (global.spread_checks != 0) {
737 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200738 err_code |= ERR_ALERT;
739 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200740 }
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200745 }
746 global.spread_checks = atol(args[1]);
747 if (global.spread_checks < 0 || global.spread_checks > 50) {
748 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200749 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 }
752 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200753 struct cfg_kw_list *kwl;
754 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200755 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200756
757 list_for_each_entry(kwl, &cfg_keywords.list, list) {
758 for (index = 0; kwl->kw[index].kw != NULL; index++) {
759 if (kwl->kw[index].section != CFG_GLOBAL)
760 continue;
761 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
762 /* prepare error message just in case */
763 snprintf(trash, sizeof(trash),
764 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200765 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
766 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200767 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200769 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200770 else if (rc > 0) {
771 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200772 err_code |= ERR_WARN;
773 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200774 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200776 }
777 }
778 }
779
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200783
Willy Tarreau058e9072009-07-20 09:30:05 +0200784 out:
785 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786}
787
Willy Tarreau97cb7802010-01-03 20:23:58 +0100788/* Perform the most basic initialization of a proxy :
789 * memset(), list_init(*), reset_timeouts(*).
790 */
791static void init_new_proxy(struct proxy *p)
792{
793 memset(p, 0, sizeof(struct proxy));
794 LIST_INIT(&p->pendconns);
795 LIST_INIT(&p->acl);
796 LIST_INIT(&p->block_cond);
797 LIST_INIT(&p->redirect_rules);
798 LIST_INIT(&p->mon_fail_cond);
799 LIST_INIT(&p->switching_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100800 LIST_INIT(&p->sticking_rules);
801 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100802 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100803 LIST_INIT(&p->req_add);
804 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100805
806 /* Timeouts are defined as -1 */
807 proxy_reset_timeouts(p);
808}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200810void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100812 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 defproxy.mode = PR_MODE_TCP;
814 defproxy.state = PR_STNEW;
815 defproxy.maxconn = cfg_maxpconn;
816 defproxy.conn_retries = CONN_RETRIES;
817 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100818
819 defproxy.defsrv.inter = DEF_CHKINTR;
820 defproxy.defsrv.fastinter = 0;
821 defproxy.defsrv.downinter = 0;
822 defproxy.defsrv.rise = DEF_RISETIME;
823 defproxy.defsrv.fall = DEF_FALLTIME;
824 defproxy.defsrv.check_port = 0;
825 defproxy.defsrv.maxqueue = 0;
826 defproxy.defsrv.minconn = 0;
827 defproxy.defsrv.maxconn = 0;
828 defproxy.defsrv.slowstart = 0;
829 defproxy.defsrv.onerror = DEF_HANA_ONERR;
830 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
831 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832}
833
834/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100835 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200836 * Returns the error code, 0 if OK, or any combination of :
837 * - ERR_ABORT: must abort ASAP
838 * - ERR_FATAL: we can continue parsing but not start the service
839 * - ERR_WARN: a warning has been emitted
840 * - ERR_ALERT: an alert has been emitted
841 * Only the two first ones can stop processing, the two others are just
842 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200844int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845{
846 static struct proxy *curproxy = NULL;
847 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200848 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100849 int rc;
850 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200851 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852
Willy Tarreau977b8e42006-12-29 14:19:17 +0100853 if (!strcmp(args[0], "listen"))
854 rc = PR_CAP_LISTEN;
855 else if (!strcmp(args[0], "frontend"))
856 rc = PR_CAP_FE | PR_CAP_RS;
857 else if (!strcmp(args[0], "backend"))
858 rc = PR_CAP_BE | PR_CAP_RS;
859 else if (!strcmp(args[0], "ruleset"))
860 rc = PR_CAP_RS;
861 else
862 rc = PR_CAP_NONE;
863
864 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200865 if (!*args[1]) {
866 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
867 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200869 err_code |= ERR_ALERT | ERR_ABORT;
870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200872
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100873 err = invalid_char(args[1]);
874 if (err) {
875 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
876 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100878 }
879
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200880 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
881 /*
882 * If there are two proxies with the same name only following
883 * combinations are allowed:
884 *
885 * listen backend frontend ruleset
886 * listen - - - -
887 * backend - - OK -
888 * frontend - OK - -
889 * ruleset - - - -
890 */
891
892 if (!strcmp(curproxy->id, args[1]) &&
893 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
894 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200895 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
896 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
897 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200898 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200899 }
900 }
901
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
903 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200904 err_code |= ERR_ALERT | ERR_ABORT;
905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100907
Willy Tarreau97cb7802010-01-03 20:23:58 +0100908 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 curproxy->next = proxy;
910 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200911 curproxy->conf.file = file;
912 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200913 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100915 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916
917 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100918 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200919 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200920 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200921 err_code |= ERR_FATAL;
922 goto out;
923 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200924 new = curproxy->listen;
925 while (new != last) {
926 new->conf.file = file;
927 new->conf.line = linenum;
928 new = new->next;
929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 global.maxsock++;
931 }
932
933 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100934 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
935
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100938 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200939 curproxy->no_options = defproxy.no_options;
940 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100941 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100942 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200943 curproxy->except_net = defproxy.except_net;
944 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200945 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200946 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200948 if (defproxy.fwdfor_hdr_len) {
949 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
950 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
951 }
952
Willy Tarreaub86db342009-11-30 11:50:16 +0100953 if (defproxy.orgto_hdr_len) {
954 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
955 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
956 }
957
Willy Tarreau977b8e42006-12-29 14:19:17 +0100958 if (curproxy->cap & PR_CAP_FE) {
959 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100960 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200961 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100962
963 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200964 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
965 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100966
967 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969
Willy Tarreau977b8e42006-12-29 14:19:17 +0100970 if (curproxy->cap & PR_CAP_BE) {
971 curproxy->fullconn = defproxy.fullconn;
972 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973
Willy Tarreau977b8e42006-12-29 14:19:17 +0100974 if (defproxy.check_req)
975 curproxy->check_req = strdup(defproxy.check_req);
976 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977
Willy Tarreau977b8e42006-12-29 14:19:17 +0100978 if (defproxy.cookie_name)
979 curproxy->cookie_name = strdup(defproxy.cookie_name);
980 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +0100981 if (defproxy.cookie_domain)
982 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +0100983
Emeric Brun647caf12009-06-30 17:57:00 +0200984 if (defproxy.rdp_cookie_name)
985 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
986 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
987
Willy Tarreau01732802007-11-01 22:48:15 +0100988 if (defproxy.url_param_name)
989 curproxy->url_param_name = strdup(defproxy.url_param_name);
990 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100991
Benoitaffb4812009-03-25 13:02:10 +0100992 if (defproxy.hh_name)
993 curproxy->hh_name = strdup(defproxy.hh_name);
994 curproxy->hh_len = defproxy.hh_len;
995 curproxy->hh_match_domain = defproxy.hh_match_domain;
996
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100997 if (defproxy.iface_name)
998 curproxy->iface_name = strdup(defproxy.iface_name);
999 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001000 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001002 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001003 if (defproxy.capture_name)
1004 curproxy->capture_name = strdup(defproxy.capture_name);
1005 curproxy->capture_namelen = defproxy.capture_namelen;
1006 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008
Willy Tarreau977b8e42006-12-29 14:19:17 +01001009 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001010 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001011 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001012 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001013 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001014 curproxy->uri_auth = defproxy.uri_auth;
1015 curproxy->mon_net = defproxy.mon_net;
1016 curproxy->mon_mask = defproxy.mon_mask;
1017 if (defproxy.monitor_uri)
1018 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1019 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001020 if (defproxy.defbe.name)
1021 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 }
1023
1024 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001025 curproxy->timeout.connect = defproxy.timeout.connect;
1026 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001027 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001028 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001029 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001030 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001031 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001032 curproxy->source_addr = defproxy.source_addr;
1033 }
1034
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 curproxy->mode = defproxy.mode;
1036 curproxy->logfac1 = defproxy.logfac1;
1037 curproxy->logsrv1 = defproxy.logsrv1;
1038 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001039 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 curproxy->logfac2 = defproxy.logfac2;
1041 curproxy->logsrv2 = defproxy.logsrv2;
1042 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001043 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001044 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001045 curproxy->conf.used_listener_id = EB_ROOT;
1046 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001047
Willy Tarreau93893792009-07-23 13:19:11 +02001048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
1050 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1051 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001052 /* FIXME-20070101: we should do this too at the end of the
1053 * config parsing to free all default values.
1054 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001055 free(defproxy.check_req);
1056 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001057 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001058 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001059 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001060 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001061 free(defproxy.capture_name);
1062 free(defproxy.monitor_uri);
1063 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001064 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001065 free(defproxy.fwdfor_hdr_name);
1066 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001067 free(defproxy.orgto_hdr_name);
1068 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001069
Willy Tarreaua534fea2008-08-03 12:19:50 +02001070 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001071 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001072
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 /* we cannot free uri_auth because it might already be used */
1074 init_default_instance();
1075 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001076 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 }
1079 else if (curproxy == NULL) {
1080 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 }
1084
Willy Tarreau977b8e42006-12-29 14:19:17 +01001085
1086 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001088 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001089 int cur_arg;
1090
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 if (curproxy == &defproxy) {
1092 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001096 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001097 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098
1099 if (strchr(args[1], ':') == NULL) {
1100 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001105
1106 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001107 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
1110 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001111
Willy Tarreau90a570f2009-10-04 20:54:54 +02001112 new_listen = curproxy->listen;
1113 while (new_listen != last_listen) {
1114 new_listen->conf.file = file;
1115 new_listen->conf.line = linenum;
1116 new_listen = new_listen->next;
1117 }
1118
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001119 cur_arg = 2;
1120 while (*(args[cur_arg])) {
1121 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1122#ifdef SO_BINDTODEVICE
1123 struct listener *l;
1124
1125 if (!*args[cur_arg + 1]) {
1126 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1127 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001130 }
1131
1132 for (l = curproxy->listen; l != last_listen; l = l->next)
1133 l->interface = strdup(args[cur_arg + 1]);
1134
1135 global.last_checks |= LSTCHK_NETADM;
1136
1137 cur_arg += 2;
1138 continue;
1139#else
1140 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1141 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001144#endif
1145 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001146 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1147#ifdef TCP_MAXSEG
1148 struct listener *l;
1149 int mss;
1150
1151 if (!*args[cur_arg + 1]) {
1152 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001156 }
1157
1158 mss = str2uic(args[cur_arg + 1]);
1159 if (mss < 1 || mss > 65535) {
1160 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1161 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001164 }
1165
1166 for (l = curproxy->listen; l != last_listen; l = l->next)
1167 l->maxseg = mss;
1168
1169 cur_arg += 2;
1170 continue;
1171#else
1172 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1173 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001176#endif
1177 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001178
1179 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1180#ifdef TCP_DEFER_ACCEPT
1181 struct listener *l;
1182
1183 for (l = curproxy->listen; l != last_listen; l = l->next)
1184 l->options |= LI_O_DEF_ACCEPT;
1185
1186 cur_arg ++;
1187 continue;
1188#else
1189 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1190 file, linenum, args[0], args[cur_arg]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193#endif
1194 }
1195
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001196 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001197#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001198 struct listener *l;
1199
1200 for (l = curproxy->listen; l != last_listen; l = l->next)
1201 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001202
1203 cur_arg ++;
1204 continue;
1205#else
1206 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1207 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001210#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001211 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001212
1213 if (!strcmp(args[cur_arg], "name")) {
1214 struct listener *l;
1215
1216 for (l = curproxy->listen; l != last_listen; l = l->next)
1217 l->name = strdup(args[cur_arg + 1]);
1218
1219 cur_arg += 2;
1220 continue;
1221 }
1222
1223 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001224 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001225 struct listener *l;
1226
1227 if (curproxy->listen->next != last_listen) {
1228 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1229 file, linenum, args[cur_arg]);
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
1232 }
1233
1234 if (!*args[cur_arg + 1]) {
1235 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1236 file, linenum, args[cur_arg]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240
1241 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001242 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001243
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001244 if (curproxy->listen->luid <= 0) {
1245 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001246 file, linenum);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001251 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1252 if (node) {
1253 l = container_of(node, struct listener, conf.id);
1254 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1255 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
1258 }
1259 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1260
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001261 cur_arg += 2;
1262 continue;
1263 }
1264
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001265 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 +01001266 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 }
1273 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1274 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1275 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001280 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001281 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001282
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 /* flush useless bits */
1284 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001286 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001287 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001288 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001289 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001290
Willy Tarreau1c47f852006-07-09 08:22:27 +02001291 if (!*args[1]) {
1292 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1293 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001294 err_code |= ERR_ALERT | ERR_FATAL;
1295 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001296 }
1297
Willy Tarreaua534fea2008-08-03 12:19:50 +02001298 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001299 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001300 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001301 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001302 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1303
Willy Tarreau93893792009-07-23 13:19:11 +02001304 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001305 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1307 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1308 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1309 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1310 else {
1311 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314 }
1315 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001316 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001317 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001318
1319 if (curproxy == &defproxy) {
1320 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1321 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001324 }
1325
1326 if (!*args[1]) {
1327 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1328 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001331 }
1332
1333 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001334 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001335
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001336 if (curproxy->uuid <= 0) {
1337 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001338 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001341 }
1342
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001343 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1344 if (node) {
1345 struct proxy *target = container_of(node, struct proxy, conf.id);
1346 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1347 file, linenum, proxy_type_str(curproxy), curproxy->id,
1348 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1349 err_code |= ERR_ALERT | ERR_FATAL;
1350 goto out;
1351 }
1352 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001353 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001354 else if (!strcmp(args[0], "description")) {
1355 int i, len=0;
1356 char *d;
1357
1358 if (!*args[1]) {
1359 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1360 file, linenum, args[0]);
1361 return -1;
1362 }
1363
1364 for(i=1; *args[i]; i++)
1365 len += strlen(args[i])+1;
1366
1367 d = (char *)calloc(1, len);
1368 curproxy->desc = d;
1369
1370 d += sprintf(d, "%s", args[1]);
1371 for(i=2; *args[i]; i++)
1372 d += sprintf(d, " %s", args[i]);
1373
1374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001375 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1376 curproxy->state = PR_STSTOPPED;
1377 }
1378 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1379 curproxy->state = PR_STNEW;
1380 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001381 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1382 int cur_arg = 1;
1383 unsigned int set = 0;
1384
1385 while (*args[cur_arg]) {
1386 int u;
1387 if (strcmp(args[cur_arg], "all") == 0) {
1388 set = 0;
1389 break;
1390 }
1391 else if (strcmp(args[cur_arg], "odd") == 0) {
1392 set |= 0x55555555;
1393 }
1394 else if (strcmp(args[cur_arg], "even") == 0) {
1395 set |= 0xAAAAAAAA;
1396 }
1397 else {
1398 u = str2uic(args[cur_arg]);
1399 if (u < 1 || u > 32) {
1400 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1401 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001402 err_code |= ERR_ALERT | ERR_FATAL;
1403 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001404 }
1405 if (u > global.nbproc) {
1406 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1407 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001408 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001409 }
1410 set |= 1 << (u - 1);
1411 }
1412 cur_arg++;
1413 }
1414 curproxy->bind_proc = set;
1415 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001416 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001417 if (curproxy == &defproxy) {
1418 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001421 }
1422
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001423 err = invalid_char(args[1]);
1424 if (err) {
1425 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1426 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001427 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001428 }
1429
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001430 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1431 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1432 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001435 }
1436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1438 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439
Willy Tarreau977b8e42006-12-29 14:19:17 +01001440 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001441 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001442
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 if (*(args[1]) == 0) {
1444 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001449
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001450 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001451 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 curproxy->cookie_name = strdup(args[1]);
1453 curproxy->cookie_len = strlen(curproxy->cookie_name);
1454
1455 cur_arg = 2;
1456 while (*(args[cur_arg])) {
1457 if (!strcmp(args[cur_arg], "rewrite")) {
1458 curproxy->options |= PR_O_COOK_RW;
1459 }
1460 else if (!strcmp(args[cur_arg], "indirect")) {
1461 curproxy->options |= PR_O_COOK_IND;
1462 }
1463 else if (!strcmp(args[cur_arg], "insert")) {
1464 curproxy->options |= PR_O_COOK_INS;
1465 }
1466 else if (!strcmp(args[cur_arg], "nocache")) {
1467 curproxy->options |= PR_O_COOK_NOC;
1468 }
1469 else if (!strcmp(args[cur_arg], "postonly")) {
1470 curproxy->options |= PR_O_COOK_POST;
1471 }
1472 else if (!strcmp(args[cur_arg], "prefix")) {
1473 curproxy->options |= PR_O_COOK_PFX;
1474 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001475 else if (!strcmp(args[cur_arg], "domain")) {
1476 if (!*args[cur_arg + 1]) {
1477 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1478 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001479 err_code |= ERR_ALERT | ERR_FATAL;
1480 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001481 }
1482
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001483 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001484 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001485 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1486 " dots nor does not start with a dot."
1487 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001488 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001489 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001490 }
1491
1492 err = invalid_domainchar(args[cur_arg + 1]);
1493 if (err) {
1494 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1495 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001498 }
1499
Willy Tarreau68a897b2009-12-03 23:28:34 +01001500 if (!curproxy->cookie_domain) {
1501 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1502 } else {
1503 /* one domain was already specified, add another one by
1504 * building the string which will be returned along with
1505 * the cookie.
1506 */
1507 char *new_ptr;
1508 int new_len = strlen(curproxy->cookie_domain) +
1509 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1510 new_ptr = malloc(new_len);
1511 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1512 free(curproxy->cookie_domain);
1513 curproxy->cookie_domain = new_ptr;
1514 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001515 cur_arg++;
1516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001517 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001518 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522 }
1523 cur_arg++;
1524 }
1525 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1526 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001528 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 }
1530
1531 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1532 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1533 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001534 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 }
1536 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001537 else if (!strcmp(args[0], "persist")) { /* persist */
1538 if (*(args[1]) == 0) {
1539 Alert("parsing [%s:%d] : missing persist method.\n",
1540 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001541 err_code |= ERR_ALERT | ERR_FATAL;
1542 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001543 }
1544
1545 if (!strncmp(args[1], "rdp-cookie", 10)) {
1546 curproxy->options2 |= PR_O2_RDPC_PRST;
1547
Emeric Brunb982a3d2010-01-04 15:45:53 +01001548 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001549 const char *beg, *end;
1550
1551 beg = args[1] + 11;
1552 end = strchr(beg, ')');
1553
1554 if (!end || end == beg) {
1555 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1556 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001557 err_code |= ERR_ALERT | ERR_FATAL;
1558 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001559 }
1560
1561 free(curproxy->rdp_cookie_name);
1562 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1563 curproxy->rdp_cookie_len = end-beg;
1564 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001565 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001566 free(curproxy->rdp_cookie_name);
1567 curproxy->rdp_cookie_name = strdup("msts");
1568 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1569 }
1570 else { /* syntax */
1571 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1572 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001575 }
1576 }
1577 else {
1578 Alert("parsing [%s:%d] : unknown persist method.\n",
1579 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001582 }
1583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001585 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001587 if (curproxy == &defproxy) {
1588 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
1591 }
1592
Willy Tarreau977b8e42006-12-29 14:19:17 +01001593 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001595
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001597 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 }
1602 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001603 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 curproxy->appsession_name = strdup(args[1]);
1605 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1606 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001607 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1608 if (err) {
1609 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1610 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001611 err_code |= ERR_ALERT | ERR_FATAL;
1612 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001613 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001614 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001615
Willy Tarreau51041c72007-09-09 21:56:53 +02001616 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1617 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_ABORT;
1619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001621
1622 cur_arg = 6;
1623 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001624 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1625 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001626 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001627 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001628 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001629 } else if (!strcmp(args[cur_arg], "prefix")) {
1630 curproxy->options2 |= PR_O2_AS_PFX;
1631 } else if (!strcmp(args[cur_arg], "mode")) {
1632 if (!*args[cur_arg + 1]) {
1633 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1634 file, linenum, args[0], args[cur_arg]);
1635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
1637 }
1638
1639 cur_arg++;
1640 if (!strcmp(args[cur_arg], "query-string")) {
1641 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1642 curproxy->options2 |= PR_O2_AS_M_QS;
1643 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1644 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1645 curproxy->options2 |= PR_O2_AS_M_PP;
1646 } else {
1647 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
1650 }
1651 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001652 cur_arg++;
1653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 } /* Url App Session */
1655 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001656 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001657 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001658
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 if (*(args[4]) == 0) {
1661 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1662 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001666 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 curproxy->capture_name = strdup(args[2]);
1668 curproxy->capture_namelen = strlen(curproxy->capture_name);
1669 curproxy->capture_len = atol(args[4]);
1670 if (curproxy->capture_len >= CAPTURE_LEN) {
1671 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1672 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 curproxy->capture_len = CAPTURE_LEN - 1;
1675 }
1676 curproxy->to_log |= LW_COOKIE;
1677 }
1678 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1679 struct cap_hdr *hdr;
1680
1681 if (curproxy == &defproxy) {
1682 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 +02001683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 }
1686
1687 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1688 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1689 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 }
1693
1694 hdr = calloc(sizeof(struct cap_hdr), 1);
1695 hdr->next = curproxy->req_cap;
1696 hdr->name = strdup(args[3]);
1697 hdr->namelen = strlen(args[3]);
1698 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001699 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700 hdr->index = curproxy->nb_req_cap++;
1701 curproxy->req_cap = hdr;
1702 curproxy->to_log |= LW_REQHDR;
1703 }
1704 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1705 struct cap_hdr *hdr;
1706
1707 if (curproxy == &defproxy) {
1708 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 +02001709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 }
1712
1713 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1714 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1715 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 }
1719 hdr = calloc(sizeof(struct cap_hdr), 1);
1720 hdr->next = curproxy->rsp_cap;
1721 hdr->name = strdup(args[3]);
1722 hdr->namelen = strlen(args[3]);
1723 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001724 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 hdr->index = curproxy->nb_rsp_cap++;
1726 curproxy->rsp_cap = hdr;
1727 curproxy->to_log |= LW_RSPHDR;
1728 }
1729 else {
1730 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1731 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001732 err_code |= ERR_ALERT | ERR_FATAL;
1733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 }
1735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001737 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740 if (*(args[1]) == 0) {
1741 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1742 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 }
1746 curproxy->conn_retries = atol(args[1]);
1747 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001748 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1749 int pol = ACL_COND_NONE;
1750 struct acl_cond *cond;
1751
Willy Tarreaub099aca2008-10-12 17:26:37 +02001752 if (curproxy == &defproxy) {
1753 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001756 }
1757
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001758 if (!strcmp(args[1], "if"))
1759 pol = ACL_COND_IF;
1760 else if (!strcmp(args[1], "unless"))
1761 pol = ACL_COND_UNLESS;
1762
1763 if (pol == ACL_COND_NONE) {
1764 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1765 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001768 }
1769
1770 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1771 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1772 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001775 }
Willy Tarreau88922352009-10-04 22:02:50 +02001776 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001777 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001778 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001779 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001780 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001781 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001782 else if (!strcmp(args[0], "redirect")) {
1783 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001784 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001785 struct redirect_rule *rule;
1786 int cur_arg;
1787 int type = REDIRECT_TYPE_NONE;
1788 int code = 302;
1789 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001790 char *cookie = NULL;
1791 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001792 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001793
1794 cur_arg = 1;
1795 while (*(args[cur_arg])) {
1796 if (!strcmp(args[cur_arg], "location")) {
1797 if (!*args[cur_arg + 1]) {
1798 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1799 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001802 }
1803
1804 type = REDIRECT_TYPE_LOCATION;
1805 cur_arg++;
1806 destination = args[cur_arg];
1807 }
1808 else if (!strcmp(args[cur_arg], "prefix")) {
1809 if (!*args[cur_arg + 1]) {
1810 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1811 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001814 }
1815
1816 type = REDIRECT_TYPE_PREFIX;
1817 cur_arg++;
1818 destination = args[cur_arg];
1819 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001820 else if (!strcmp(args[cur_arg], "set-cookie")) {
1821 if (!*args[cur_arg + 1]) {
1822 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1823 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001826 }
1827
1828 cur_arg++;
1829 cookie = args[cur_arg];
1830 cookie_set = 1;
1831 }
1832 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1833 if (!*args[cur_arg + 1]) {
1834 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1835 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001838 }
1839
1840 cur_arg++;
1841 cookie = args[cur_arg];
1842 cookie_set = 0;
1843 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001844 else if (!strcmp(args[cur_arg],"code")) {
1845 if (!*args[cur_arg + 1]) {
1846 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1847 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001850 }
1851 cur_arg++;
1852 code = atol(args[cur_arg]);
1853 if (code < 301 || code > 303) {
1854 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1855 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_ALERT | ERR_FATAL;
1857 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001858 }
1859 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001860 else if (!strcmp(args[cur_arg],"drop-query")) {
1861 flags |= REDIRECT_FLAG_DROP_QS;
1862 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001863 else if (!strcmp(args[cur_arg],"append-slash")) {
1864 flags |= REDIRECT_FLAG_APPEND_SLASH;
1865 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001866 else if (!strcmp(args[cur_arg], "if")) {
1867 pol = ACL_COND_IF;
1868 cur_arg++;
1869 break;
1870 }
1871 else if (!strcmp(args[cur_arg], "unless")) {
1872 pol = ACL_COND_UNLESS;
1873 cur_arg++;
1874 break;
1875 }
1876 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001877 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 +02001878 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001879 err_code |= ERR_ALERT | ERR_FATAL;
1880 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001881 }
1882 cur_arg++;
1883 }
1884
1885 if (type == REDIRECT_TYPE_NONE) {
1886 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001890 }
1891
Willy Tarreauf285f542010-01-03 20:03:03 +01001892 if (pol != ACL_COND_NONE &&
1893 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001894 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001895 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001898 }
1899
Willy Tarreauf285f542010-01-03 20:03:03 +01001900 if (cond) {
1901 cond->file = file;
1902 cond->line = linenum;
1903 curproxy->acl_requires |= cond->requires;
1904 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001905 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1906 rule->cond = cond;
1907 rule->rdr_str = strdup(destination);
1908 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001909 if (cookie) {
1910 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1911 * a clear consists in appending "; Max-Age=0" at the end.
1912 */
1913 rule->cookie_len = strlen(cookie);
1914 if (cookie_set)
1915 rule->cookie_str = strdup(cookie);
1916 else {
1917 rule->cookie_str = malloc(rule->cookie_len + 12);
1918 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1919 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1920 rule->cookie_len += 11;
1921 }
1922 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001923 rule->type = type;
1924 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001925 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001926 LIST_INIT(&rule->list);
1927 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001928 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001929 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001930 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001931 int pol = ACL_COND_NONE;
1932 struct acl_cond *cond;
1933 struct switching_rule *rule;
1934
Willy Tarreaub099aca2008-10-12 17:26:37 +02001935 if (curproxy == &defproxy) {
1936 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_ALERT | ERR_FATAL;
1938 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001939 }
1940
Willy Tarreau55ea7572007-06-17 19:56:27 +02001941 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001943
1944 if (*(args[1]) == 0) {
1945 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001948 }
1949
1950 if (!strcmp(args[2], "if"))
1951 pol = ACL_COND_IF;
1952 else if (!strcmp(args[2], "unless"))
1953 pol = ACL_COND_UNLESS;
1954
1955 if (pol == ACL_COND_NONE) {
1956 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1957 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
1959 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001960 }
1961
1962 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001963 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001964 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001967 }
1968
Willy Tarreau88922352009-10-04 22:02:50 +02001969 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001970 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001971 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001972 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001973 struct acl *acl;
1974 const char *name;
1975
1976 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1977 name = acl ? acl->name : "(unknown)";
1978 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1979 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001981 }
1982
Willy Tarreau55ea7572007-06-17 19:56:27 +02001983 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1984 rule->cond = cond;
1985 rule->be.name = strdup(args[1]);
1986 LIST_INIT(&rule->list);
1987 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1988 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001989 else if (!strcmp(args[0], "stick-table")) {
1990 int myidx = 1;
1991
1992 curproxy->table.type = (unsigned int)-1;
1993 while (*args[myidx]) {
1994 const char *err;
1995
1996 if (strcmp(args[myidx], "size") == 0) {
1997 myidx++;
1998 if (!*(args[myidx])) {
1999 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2000 file, linenum, args[myidx-1]);
2001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
2003 }
2004 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2005 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2006 file, linenum, *err, args[myidx-1]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010 }
2011 else if (strcmp(args[myidx], "expire") == 0) {
2012 myidx++;
2013 if (!*(args[myidx])) {
2014 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2015 file, linenum, args[myidx-1]);
2016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
2018 }
2019 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2020 if (err) {
2021 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2022 file, linenum, *err, args[myidx-1]);
2023 err_code |= ERR_ALERT | ERR_FATAL;
2024 goto out;
2025 }
2026 curproxy->table.expire = val;
2027 }
2028 else if (strcmp(args[myidx], "nopurge") == 0) {
2029 curproxy->table.nopurge = 1;
2030 }
2031 else if (strcmp(args[myidx], "type") == 0) {
2032 myidx++;
2033 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2034 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2035 file, linenum, args[myidx]);
2036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
2038 }
2039 }
2040 myidx++;
2041 }
2042
2043 if (!curproxy->table.size) {
2044 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2045 file, linenum);
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
2050 if (curproxy->table.type == (unsigned int)-1) {
2051 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2052 file, linenum);
2053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
2055 }
2056 }
2057 else if (!strcmp(args[0], "stick")) {
2058 int pol = ACL_COND_NONE;
2059 struct acl_cond *cond = NULL;
2060 struct sticking_rule *rule;
2061 struct pattern_expr *expr;
2062 int myidx = 0;
2063 const char *name = NULL;
2064 int flags;
2065
2066 if (curproxy == &defproxy) {
2067 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
2070 }
2071
2072 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2073 err_code |= ERR_WARN;
2074 goto out;
2075 }
2076
2077 myidx++;
2078 if ((strcmp(args[myidx], "store") == 0) ||
2079 (strcmp(args[myidx], "store-request") == 0)) {
2080 myidx++;
2081 flags = STK_IS_STORE;
2082 }
2083 else if (strcmp(args[myidx], "store-response") == 0) {
2084 myidx++;
2085 flags = STK_IS_STORE | STK_ON_RSP;
2086 }
2087 else if (strcmp(args[myidx], "match") == 0) {
2088 myidx++;
2089 flags = STK_IS_MATCH;
2090 }
2091 else if (strcmp(args[myidx], "on") == 0) {
2092 myidx++;
2093 flags = STK_IS_MATCH | STK_IS_STORE;
2094 }
2095 else {
2096 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
2099 }
2100
2101 if (*(args[myidx]) == 0) {
2102 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
2105 }
2106
2107 expr = pattern_parse_expr(args, &myidx);
2108 if (!expr) {
2109 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
2112 }
2113
2114 if (flags & STK_ON_RSP) {
2115 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2116 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2117 file, linenum, args[0], expr->fetch->kw);
2118 err_code |= ERR_ALERT | ERR_FATAL;
2119 goto out;
2120 }
2121 } else {
2122 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2123 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2124 file, linenum, args[0], expr->fetch->kw);
2125 err_code |= ERR_ALERT | ERR_FATAL;
2126 goto out;
2127 }
2128 }
2129
2130 if (strcmp(args[myidx], "table") == 0) {
2131 myidx++;
2132 name = args[myidx++];
2133 }
2134
2135 if (*(args[myidx]) == 0)
2136 pol = ACL_COND_NONE;
2137 else if (strcmp(args[myidx], "if") == 0)
2138 pol = ACL_COND_IF;
2139 else if (strcmp(args[myidx], "unless") == 0)
2140 pol = ACL_COND_UNLESS;
2141 else {
2142 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2143 file, linenum, args[0], args[myidx]);
2144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
2146 }
2147
2148 if (pol != ACL_COND_NONE) {
2149 myidx++;
2150 if ((cond = parse_acl_cond((const char **)args + myidx, &curproxy->acl, pol)) == NULL) {
2151 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2152 file, linenum, args[0]);
2153 err_code |= ERR_ALERT | ERR_FATAL;
2154 goto out;
2155 }
2156
2157 cond->file = file;
2158 cond->line = linenum;
2159 curproxy->acl_requires |= cond->requires;
2160 if (cond->requires & ACL_USE_RTR_ANY) {
2161 struct acl *acl;
2162 const char *name;
2163
2164 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2165 name = acl ? acl->name : "(unknown)";
2166 Warning("parsing [%s:%d] : '%s' : acl '%s' involves some response-only criteria which will be ignored.\n",
2167 file, linenum, args[0], name);
2168 err_code |= ERR_WARN;
2169 }
2170 }
2171 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2172 rule->cond = cond;
2173 rule->expr = expr;
2174 rule->flags = flags;
2175 rule->table.name = name ? strdup(name) : NULL;
2176 LIST_INIT(&rule->list);
2177 if (flags & STK_ON_RSP)
2178 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2179 else
2180 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002183 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002185
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2187 curproxy->uri_auth = NULL; /* we must detach from the default config */
2188
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002189 if (!*args[1]) {
2190 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 } else if (!strcmp(args[1], "uri")) {
2192 if (*(args[2]) == 0) {
2193 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_ALERT | ERR_ABORT;
2199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 }
2201 } else if (!strcmp(args[1], "realm")) {
2202 if (*(args[2]) == 0) {
2203 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2207 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_ALERT | ERR_ABORT;
2209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002211 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002212 unsigned interval;
2213
2214 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2215 if (err) {
2216 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2217 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002220 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2221 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_ABORT;
2223 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 } else if (!strcmp(args[1], "auth")) {
2226 if (*(args[2]) == 0) {
2227 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2231 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_ABORT;
2233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
2235 } else if (!strcmp(args[1], "scope")) {
2236 if (*(args[2]) == 0) {
2237 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_ABORT;
2243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 }
2245 } else if (!strcmp(args[1], "enable")) {
2246 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2247 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_ABORT;
2249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002251 } else if (!strcmp(args[1], "hide-version")) {
2252 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_ABORT;
2255 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002256 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002257 } else if (!strcmp(args[1], "show-legends")) {
2258 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2259 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2260 err_code |= ERR_ALERT | ERR_ABORT;
2261 goto out;
2262 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002263 } else if (!strcmp(args[1], "show-node")) {
2264
2265 if (*args[2]) {
2266 int i;
2267 char c;
2268
2269 for (i=0; args[2][i]; i++) {
2270 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002271 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002272 break;
2273 }
2274
2275 if (!i || args[2][i]) {
2276 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2277 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2278 file, linenum, args[0], args[1]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282 }
2283
2284 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2285 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2286 err_code |= ERR_ALERT | ERR_ABORT;
2287 goto out;
2288 }
2289 } else if (!strcmp(args[1], "show-desc")) {
2290 char *desc = NULL;
2291
2292 if (*args[2]) {
2293 int i, len=0;
2294 char *d;
2295
2296 for(i=2; *args[i]; i++)
2297 len += strlen(args[i])+1;
2298
2299 desc = d = (char *)calloc(1, len);
2300
2301 d += sprintf(d, "%s", args[2]);
2302 for(i=3; *args[i]; i++)
2303 d += sprintf(d, " %s", args[i]);
2304 }
2305
2306 if (!*args[2] && !global.desc)
2307 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2308 file, linenum, args[1]);
2309 else {
2310 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2311 free(desc);
2312 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2313 err_code |= ERR_ALERT | ERR_ABORT;
2314 goto out;
2315 }
2316 free(desc);
2317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002319stats_error_parsing:
2320 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2321 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 }
2325 }
2326 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002327 int optnum;
2328
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002329 if (*(args[1]) == '\0') {
2330 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2331 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002335
2336 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2337 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002338 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2339 err_code |= ERR_WARN;
2340 goto out;
2341 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002342
Willy Tarreau3842f002009-06-14 11:39:52 +02002343 curproxy->no_options &= ~cfg_opts[optnum].val;
2344 curproxy->options &= ~cfg_opts[optnum].val;
2345
2346 switch (kwm) {
2347 case KWM_STD:
2348 curproxy->options |= cfg_opts[optnum].val;
2349 break;
2350 case KWM_NO:
2351 curproxy->no_options |= cfg_opts[optnum].val;
2352 break;
2353 case KWM_DEF: /* already cleared */
2354 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002355 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002356
Willy Tarreau93893792009-07-23 13:19:11 +02002357 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002358 }
2359 }
2360
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002361 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2362 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002363 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2364 err_code |= ERR_WARN;
2365 goto out;
2366 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002367
Willy Tarreau3842f002009-06-14 11:39:52 +02002368 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2369 curproxy->options2 &= ~cfg_opts2[optnum].val;
2370
2371 switch (kwm) {
2372 case KWM_STD:
2373 curproxy->options2 |= cfg_opts2[optnum].val;
2374 break;
2375 case KWM_NO:
2376 curproxy->no_options2 |= cfg_opts2[optnum].val;
2377 break;
2378 case KWM_DEF: /* already cleared */
2379 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002380 }
Willy Tarreau93893792009-07-23 13:19:11 +02002381 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002382 }
2383 }
2384
Willy Tarreau3842f002009-06-14 11:39:52 +02002385 if (kwm != KWM_STD) {
2386 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002387 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002390 }
2391
Emeric Brun3a058f32009-06-30 18:26:00 +02002392 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002394 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002396 if (*(args[2]) != '\0') {
2397 if (!strcmp(args[2], "clf")) {
2398 curproxy->options2 |= PR_O2_CLFLOG;
2399 } else {
2400 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002403 }
2404 }
2405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 else if (!strcmp(args[1], "tcplog"))
2407 /* generate a detailed TCP log */
2408 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 else if (!strcmp(args[1], "tcpka")) {
2410 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002411 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002413
2414 if (curproxy->cap & PR_CAP_FE)
2415 curproxy->options |= PR_O_TCP_CLI_KA;
2416 if (curproxy->cap & PR_CAP_BE)
2417 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 }
2419 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002420 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002421 err_code |= ERR_WARN;
2422
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002424 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002425 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002426 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002427 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002428 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 if (!*args[2]) { /* no argument */
2430 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2431 curproxy->check_len = strlen(DEF_CHECK_REQ);
2432 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002433 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 curproxy->check_req = (char *)malloc(reqlen);
2435 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2436 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2437 } else { /* more arguments : METHOD URI [HTTP_VER] */
2438 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2439 if (*args[4])
2440 reqlen += strlen(args[4]);
2441 else
2442 reqlen += strlen("HTTP/1.0");
2443
2444 curproxy->check_req = (char *)malloc(reqlen);
2445 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2446 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2447 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002448 }
2449 else if (!strcmp(args[1], "ssl-hello-chk")) {
2450 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002451 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002453
Willy Tarreaua534fea2008-08-03 12:19:50 +02002454 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002455 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002456 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002457 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002458 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 }
Willy Tarreau23677902007-05-08 23:50:35 +02002460 else if (!strcmp(args[1], "smtpchk")) {
2461 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002462 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002463 curproxy->options &= ~PR_O_HTTP_CHK;
2464 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002465 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002466 curproxy->options |= PR_O_SMTP_CHK;
2467
2468 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2469 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2470 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2471 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2472 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2473 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2474 curproxy->check_req = (char *)malloc(reqlen);
2475 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2476 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2477 } else {
2478 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2479 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2480 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2481 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2482 }
2483 }
2484 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002485 else if (!strcmp(args[1], "mysql-check")) {
2486 /* use MYSQL request to check servers' health */
2487 free(curproxy->check_req);
2488 curproxy->options &= ~PR_O_HTTP_CHK;
2489 curproxy->options &= ~PR_O_SSL3_CHK;
2490 curproxy->options &= ~PR_O_SMTP_CHK;
2491 curproxy->options2 |= PR_O2_MYSQL_CHK;
2492 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002493 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002494 int cur_arg;
2495
2496 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2497 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002498 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002499
2500 curproxy->options |= PR_O_FWDFOR;
2501
2502 free(curproxy->fwdfor_hdr_name);
2503 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2504 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2505
2506 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2507 cur_arg = 2;
2508 while (*(args[cur_arg])) {
2509 if (!strcmp(args[cur_arg], "except")) {
2510 /* suboption except - needs additional argument for it */
2511 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2512 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2513 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002516 }
2517 /* flush useless bits */
2518 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002519 cur_arg += 2;
2520 } else if (!strcmp(args[cur_arg], "header")) {
2521 /* suboption header - needs additional argument for it */
2522 if (*(args[cur_arg+1]) == 0) {
2523 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2524 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002527 }
2528 free(curproxy->fwdfor_hdr_name);
2529 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2530 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2531 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002532 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002533 /* unknown suboption - catchall */
2534 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2535 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002538 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002539 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002540 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002541 else if (!strcmp(args[1], "originalto")) {
2542 int cur_arg;
2543
2544 /* insert x-original-to field, but not for the IP address listed as an except.
2545 * set default options (ie: bitfield, header name, etc)
2546 */
2547
2548 curproxy->options |= PR_O_ORGTO;
2549
2550 free(curproxy->orgto_hdr_name);
2551 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2552 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2553
2554 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2555 cur_arg = 2;
2556 while (*(args[cur_arg])) {
2557 if (!strcmp(args[cur_arg], "except")) {
2558 /* suboption except - needs additional argument for it */
2559 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2560 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2561 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002564 }
2565 /* flush useless bits */
2566 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2567 cur_arg += 2;
2568 } else if (!strcmp(args[cur_arg], "header")) {
2569 /* suboption header - needs additional argument for it */
2570 if (*(args[cur_arg+1]) == 0) {
2571 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2572 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002575 }
2576 free(curproxy->orgto_hdr_name);
2577 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2578 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2579 cur_arg += 2;
2580 } else {
2581 /* unknown suboption - catchall */
2582 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2583 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002586 }
2587 } /* end while loop */
2588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 else {
2590 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 }
Willy Tarreau93893792009-07-23 13:19:11 +02002594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002596 else if (!strcmp(args[0], "default_backend")) {
2597 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002599
2600 if (*(args[1]) == 0) {
2601 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002604 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002605 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002606 curproxy->defbe.name = strdup(args[1]);
2607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002612 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2613 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 /* enable reconnections to dispatch */
2616 curproxy->options |= PR_O_REDISP;
2617 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002618 else if (!strcmp(args[0], "http-check")) {
2619 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002621
2622 if (strcmp(args[1], "disable-on-404") == 0) {
2623 /* enable a graceful server shutdown on an HTTP 404 response */
2624 curproxy->options |= PR_O_DISABLE404;
2625 }
2626 else {
2627 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002630 }
2631 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002632 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002633 if (curproxy == &defproxy) {
2634 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002637 }
2638
Willy Tarreaub80c2302007-11-30 20:51:32 +01002639 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002641
2642 if (strcmp(args[1], "fail") == 0) {
2643 /* add a condition to fail monitor requests */
2644 int pol = ACL_COND_NONE;
2645 struct acl_cond *cond;
2646
2647 if (!strcmp(args[2], "if"))
2648 pol = ACL_COND_IF;
2649 else if (!strcmp(args[2], "unless"))
2650 pol = ACL_COND_UNLESS;
2651
2652 if (pol == ACL_COND_NONE) {
2653 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2654 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002657 }
2658
2659 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2660 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2661 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002664 }
Willy Tarreau88922352009-10-04 22:02:50 +02002665 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002666 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002667 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002668 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2669 }
2670 else {
2671 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002674 }
2675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676#ifdef TPROXY
2677 else if (!strcmp(args[0], "transparent")) {
2678 /* enable transparent proxy connections */
2679 curproxy->options |= PR_O_TRANSP;
2680 }
2681#endif
2682 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002684 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002685
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 if (*(args[1]) == 0) {
2687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 }
2691 curproxy->maxconn = atol(args[1]);
2692 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002693 else if (!strcmp(args[0], "backlog")) { /* backlog */
2694 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002695 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002696
2697 if (*(args[1]) == 0) {
2698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002701 }
2702 curproxy->backlog = atol(args[1]);
2703 }
Willy Tarreau86034312006-12-29 00:10:33 +01002704 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002705 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002707
Willy Tarreau86034312006-12-29 00:10:33 +01002708 if (*(args[1]) == 0) {
2709 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002712 }
2713 curproxy->fullconn = atol(args[1]);
2714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2716 if (*(args[1]) == 0) {
2717 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002721 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2722 if (err) {
2723 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2724 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002727 }
2728 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 }
2730 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2731 if (curproxy == &defproxy) {
2732 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002736 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002737 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 if (strchr(args[1], ':') == NULL) {
2740 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 }
2744 curproxy->dispatch_addr = *str2sa(args[1]);
2745 }
2746 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002750 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002751 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2752 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002757 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2759 err_code |= ERR_WARN;
2760
2761 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2762 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2763 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2764 }
2765 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2766 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2767 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2768 }
2769 else {
2770 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002775 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002777 char *rport, *raddr;
2778 short realport = 0;
2779 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002781 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788
2789 if (!*args[2]) {
2790 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2791 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002795
2796 err = invalid_char(args[1]);
2797 if (err) {
2798 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2799 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002802 }
2803
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2805 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_ABORT;
2807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 }
2809
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002810 if (!defsrv) {
2811 /* the servers are linked backwards first */
2812 newsrv->next = curproxy->srv;
2813 curproxy->srv = newsrv;
2814 newsrv->proxy = curproxy;
2815 newsrv->conf.file = file;
2816 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002818 LIST_INIT(&newsrv->pendconns);
2819 do_check = 0;
2820 newsrv->state = SRV_RUNNING; /* early server setup */
2821 newsrv->last_change = now.tv_sec;
2822 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002824 /* several ways to check the port component :
2825 * - IP => port=+0, relative
2826 * - IP: => port=+0, relative
2827 * - IP:N => port=N, absolute
2828 * - IP:+N => port=+N, relative
2829 * - IP:-N => port=-N, relative
2830 */
2831 raddr = strdup(args[2]);
2832 rport = strchr(raddr, ':');
2833 if (rport) {
2834 *rport++ = 0;
2835 realport = atol(rport);
2836 if (!isdigit((unsigned char)*rport))
2837 newsrv->state |= SRV_MAPPORTS;
2838 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002840
2841 newsrv->addr = *str2sa(raddr);
2842 newsrv->addr.sin_port = htons(realport);
2843 free(raddr);
2844
2845 newsrv->check_port = curproxy->defsrv.check_port;
2846 newsrv->inter = curproxy->defsrv.inter;
2847 newsrv->fastinter = curproxy->defsrv.fastinter;
2848 newsrv->downinter = curproxy->defsrv.downinter;
2849 newsrv->rise = curproxy->defsrv.rise;
2850 newsrv->fall = curproxy->defsrv.fall;
2851 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2852 newsrv->minconn = curproxy->defsrv.minconn;
2853 newsrv->maxconn = curproxy->defsrv.maxconn;
2854 newsrv->slowstart = curproxy->defsrv.slowstart;
2855 newsrv->onerror = curproxy->defsrv.onerror;
2856 newsrv->consecutive_errors_limit
2857 = curproxy->defsrv.consecutive_errors_limit;
2858 newsrv->uweight = newsrv->iweight
2859 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002861 newsrv->curfd = -1; /* no health-check in progress */
2862 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002864 cur_arg = 3;
2865 } else {
2866 newsrv = &curproxy->defsrv;
2867 cur_arg = 1;
2868 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002869
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002871 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002872 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002873
2874 if (!*args[cur_arg + 1]) {
2875 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2876 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002879 }
2880
2881 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002882 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002883
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002884 if (newsrv->puid <= 0) {
2885 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002886 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002889 }
2890
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002891 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2892 if (node) {
2893 struct server *target = container_of(node, struct server, conf.id);
2894 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2895 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002900 cur_arg += 2;
2901 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002902 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 newsrv->cookie = strdup(args[cur_arg + 1]);
2904 newsrv->cklen = strlen(args[cur_arg + 1]);
2905 cur_arg += 2;
2906 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002907 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01002908 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2909 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2910 cur_arg += 2;
2911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002913 if (!*args[cur_arg + 1]) {
2914 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2915 file, linenum, args[cur_arg]);
2916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002921 if (newsrv->rise <= 0) {
2922 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2923 file, linenum, args[cur_arg]);
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926 }
2927
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 newsrv->health = newsrv->rise;
2929 cur_arg += 2;
2930 }
2931 else if (!strcmp(args[cur_arg], "fall")) {
2932 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002933
2934 if (!*args[cur_arg + 1]) {
2935 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2936 file, linenum, args[cur_arg]);
2937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
2939 }
2940
2941 if (newsrv->fall <= 0) {
2942 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2943 file, linenum, args[cur_arg]);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946 }
2947
Willy Tarreaubaaee002006-06-26 02:48:02 +02002948 cur_arg += 2;
2949 }
2950 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002951 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2952 if (err) {
2953 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2954 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002957 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002958 if (val <= 0) {
2959 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2960 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002963 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002964 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 cur_arg += 2;
2966 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002967 else if (!strcmp(args[cur_arg], "fastinter")) {
2968 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2969 if (err) {
2970 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2971 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002974 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002975 if (val <= 0) {
2976 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2977 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002980 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002981 newsrv->fastinter = val;
2982 cur_arg += 2;
2983 }
2984 else if (!strcmp(args[cur_arg], "downinter")) {
2985 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2986 if (err) {
2987 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2988 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002991 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002992 if (val <= 0) {
2993 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2994 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002997 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002998 newsrv->downinter = val;
2999 cur_arg += 2;
3000 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003001 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003002 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003003 cur_arg += 2;
3004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 else if (!strcmp(args[cur_arg], "port")) {
3006 newsrv->check_port = atol(args[cur_arg + 1]);
3007 cur_arg += 2;
3008 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003009 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 newsrv->state |= SRV_BACKUP;
3011 cur_arg ++;
3012 }
3013 else if (!strcmp(args[cur_arg], "weight")) {
3014 int w;
3015 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003016 if (w < 0 || w > 256) {
3017 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003022 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 cur_arg += 2;
3024 }
3025 else if (!strcmp(args[cur_arg], "minconn")) {
3026 newsrv->minconn = atol(args[cur_arg + 1]);
3027 cur_arg += 2;
3028 }
3029 else if (!strcmp(args[cur_arg], "maxconn")) {
3030 newsrv->maxconn = atol(args[cur_arg + 1]);
3031 cur_arg += 2;
3032 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003033 else if (!strcmp(args[cur_arg], "maxqueue")) {
3034 newsrv->maxqueue = atol(args[cur_arg + 1]);
3035 cur_arg += 2;
3036 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003037 else if (!strcmp(args[cur_arg], "slowstart")) {
3038 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003039 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003040 if (err) {
3041 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3042 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003045 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003046 if (val <= 0) {
3047 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3048 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003051 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003052 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003053 cur_arg += 2;
3054 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003055 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003056
3057 if (!*args[cur_arg + 1]) {
3058 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3059 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003062 }
3063
3064 newsrv->trackit = strdup(args[cur_arg + 1]);
3065
3066 cur_arg += 2;
3067 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003068 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 global.maxsock++;
3070 do_check = 1;
3071 cur_arg += 1;
3072 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003073 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003074 if (!strcmp(args[cur_arg + 1], "none"))
3075 newsrv->observe = HANA_OBS_NONE;
3076 else if (!strcmp(args[cur_arg + 1], "layer4"))
3077 newsrv->observe = HANA_OBS_LAYER4;
3078 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3079 if (curproxy->mode != PR_MODE_HTTP) {
3080 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3081 file, linenum, args[cur_arg + 1]);
3082 err_code |= ERR_ALERT;
3083 }
3084 newsrv->observe = HANA_OBS_LAYER7;
3085 }
3086 else {
3087 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3088 "'l4events', 'http-responses' but get '%s'\n",
3089 file, linenum, args[cur_arg], args[cur_arg + 1]);
3090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
3092 }
3093
3094 cur_arg += 2;
3095 }
3096 else if (!strcmp(args[cur_arg], "on-error")) {
3097 if (!strcmp(args[cur_arg + 1], "fastinter"))
3098 newsrv->onerror = HANA_ONERR_FASTINTER;
3099 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3100 newsrv->onerror = HANA_ONERR_FAILCHK;
3101 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3102 newsrv->onerror = HANA_ONERR_SUDDTH;
3103 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3104 newsrv->onerror = HANA_ONERR_MARKDWN;
3105 else {
3106 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3107 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3108 file, linenum, args[cur_arg], args[cur_arg + 1]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
3112
3113 cur_arg += 2;
3114 }
3115 else if (!strcmp(args[cur_arg], "error-limit")) {
3116 if (!*args[cur_arg + 1]) {
3117 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3118 file, linenum, args[cur_arg]);
3119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121 }
3122
3123 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3124
3125 if (newsrv->consecutive_errors_limit <= 0) {
3126 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3127 file, linenum, args[cur_arg]);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003132 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003133 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003135#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003136 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003137 file, linenum, "source", "usesrc");
3138#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003139 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003141#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 }
3145 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003146 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3147
3148 if (port_low != port_high) {
3149 int i;
3150 if (port_low <= 0 || port_low > 65535 ||
3151 port_high <= 0 || port_high > 65535 ||
3152 port_low > port_high) {
3153 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3154 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003157 }
3158 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3159 for (i = 0; i < newsrv->sport_range->size; i++)
3160 newsrv->sport_range->ports[i] = port_low + i;
3161 }
3162
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003164 while (*(args[cur_arg])) {
3165 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003166#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3167#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003168 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3169 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3170 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003173 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003174#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003175 if (!*args[cur_arg + 1]) {
3176 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3177 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003180 }
3181 if (!strcmp(args[cur_arg + 1], "client")) {
3182 newsrv->state |= SRV_TPROXY_CLI;
3183 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3184 newsrv->state |= SRV_TPROXY_CIP;
3185 } else {
3186 newsrv->state |= SRV_TPROXY_ADDR;
3187 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3188 }
3189 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003190#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003191 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003192#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003193 cur_arg += 2;
3194 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003195#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003196 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003197 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003200#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3201 } /* "usesrc" */
3202
3203 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3204#ifdef SO_BINDTODEVICE
3205 if (!*args[cur_arg + 1]) {
3206 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3207 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003210 }
3211 if (newsrv->iface_name)
3212 free(newsrv->iface_name);
3213
3214 newsrv->iface_name = strdup(args[cur_arg + 1]);
3215 newsrv->iface_len = strlen(newsrv->iface_name);
3216 global.last_checks |= LSTCHK_NETADM;
3217#else
3218 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3219 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003222#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003223 cur_arg += 2;
3224 continue;
3225 }
3226 /* this keyword in not an option of "source" */
3227 break;
3228 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003230 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003231 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3232 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003237 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003238 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 +01003239 file, linenum, newsrv->id);
3240 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003241 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 +01003242 file, linenum);
3243
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 }
3247 }
3248
3249 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003250 if (newsrv->trackit) {
3251 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3252 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003255 }
3256
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003257 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3258 newsrv->check_port = newsrv->check_addr.sin_port;
3259
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3261 newsrv->check_port = realport; /* by default */
3262 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003263 /* not yet valid, because no port was set on
3264 * the server either. We'll check if we have
3265 * a known port on the first listener.
3266 */
3267 struct listener *l;
3268 l = curproxy->listen;
3269 if (l) {
3270 int port;
3271 port = (l->addr.ss_family == AF_INET6)
3272 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3273 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3274 newsrv->check_port = port;
3275 }
3276 }
3277 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3279 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003283
3284 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 newsrv->state |= SRV_CHECKED;
3286 }
3287
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003288 if (!defsrv) {
3289 if (newsrv->state & SRV_BACKUP)
3290 curproxy->srv_bck++;
3291 else
3292 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003293
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003294 newsrv->prev_state = newsrv->state;
3295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
3297 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003298 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 int facility;
3300
3301 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3302 curproxy->logfac1 = global.logfac1;
3303 curproxy->logsrv1 = global.logsrv1;
3304 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003305 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 curproxy->logfac2 = global.logfac2;
3307 curproxy->logsrv2 = global.logsrv2;
3308 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003309 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003312 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313
3314 facility = get_log_facility(args[2]);
3315 if (facility < 0) {
3316 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3317 exit(1);
3318 }
3319
3320 level = 7; /* max syslog level = debug */
3321 if (*(args[3])) {
3322 level = get_log_level(args[3]);
3323 if (level < 0) {
3324 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3325 exit(1);
3326 }
3327 }
3328
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003329 minlvl = 0; /* limit syslog level to this level (emerg) */
3330 if (*(args[4])) {
3331 minlvl = get_log_level(args[4]);
3332 if (level < 0) {
3333 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3334 exit(1);
3335 }
3336 }
3337
Robert Tsai81ae1952007-12-05 10:47:29 +01003338 if (args[1][0] == '/') {
3339 logsrv.u.addr.sa_family = AF_UNIX;
3340 logsrv.u.un = *str2sun(args[1]);
3341 } else {
3342 logsrv.u.addr.sa_family = AF_INET;
3343 logsrv.u.in = *str2sa(args[1]);
3344 if (!logsrv.u.in.sin_port) {
3345 logsrv.u.in.sin_port =
3346 htons(SYSLOG_PORT);
3347 }
3348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349
3350 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003351 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 curproxy->logfac1 = facility;
3353 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003354 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
3356 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003357 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 curproxy->logfac2 = facility;
3359 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003360 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 }
3362 else {
3363 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
3367 }
3368 else {
3369 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3370 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
3374 }
3375 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003376 int cur_arg;
3377
Willy Tarreau977b8e42006-12-29 14:19:17 +01003378 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003380
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003382 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3383 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003387
3388 /* we must first clear any optional default setting */
3389 curproxy->options &= ~PR_O_TPXY_MASK;
3390 free(curproxy->iface_name);
3391 curproxy->iface_name = NULL;
3392 curproxy->iface_len = 0;
3393
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 curproxy->source_addr = *str2sa(args[1]);
3395 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003396
3397 cur_arg = 2;
3398 while (*(args[cur_arg])) {
3399 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003400#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3401#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003402 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3403 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3404 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003407 }
3408#endif
3409 if (!*args[cur_arg + 1]) {
3410 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3411 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003414 }
3415
3416 if (!strcmp(args[cur_arg + 1], "client")) {
3417 curproxy->options |= PR_O_TPXY_CLI;
3418 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3419 curproxy->options |= PR_O_TPXY_CIP;
3420 } else {
3421 curproxy->options |= PR_O_TPXY_ADDR;
3422 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3423 }
3424 global.last_checks |= LSTCHK_NETADM;
3425#if !defined(CONFIG_HAP_LINUX_TPROXY)
3426 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003427#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003428#else /* no TPROXY support */
3429 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003430 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003433#endif
3434 cur_arg += 2;
3435 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003436 }
3437
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003438 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3439#ifdef SO_BINDTODEVICE
3440 if (!*args[cur_arg + 1]) {
3441 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3442 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003445 }
3446 if (curproxy->iface_name)
3447 free(curproxy->iface_name);
3448
3449 curproxy->iface_name = strdup(args[cur_arg + 1]);
3450 curproxy->iface_len = strlen(curproxy->iface_name);
3451 global.last_checks |= LSTCHK_NETADM;
3452#else
3453 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3454 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003457#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003458 cur_arg += 2;
3459 continue;
3460 }
3461 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3462 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003467 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3468 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3469 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3474 regex_t *preg;
3475 if (curproxy == &defproxy) {
3476 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003480 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003482
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 if (*(args[1]) == 0 || *(args[2]) == 0) {
3484 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3485 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003486 err_code |= ERR_ALERT | ERR_FATAL;
3487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003488 }
3489
3490 preg = calloc(1, sizeof(regex_t));
3491 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3492 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 }
3496
3497 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3498 if (err) {
3499 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3500 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003503 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 }
3505 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3506 regex_t *preg;
3507 if (curproxy == &defproxy) {
3508 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003512 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003514
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 if (*(args[1]) == 0) {
3516 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 }
3520
3521 preg = calloc(1, sizeof(regex_t));
3522 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3523 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 }
3527
3528 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003529 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 }
3531 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3532 regex_t *preg;
3533 if (curproxy == &defproxy) {
3534 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003538 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003540
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 if (*(args[1]) == 0) {
3542 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 }
3546
3547 preg = calloc(1, sizeof(regex_t));
3548 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3549 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 }
3553
3554 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003555 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003556 }
3557 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3558 regex_t *preg;
3559 if (curproxy == &defproxy) {
3560 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003564 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003566
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 if (*(args[1]) == 0) {
3568 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 }
3572
3573 preg = calloc(1, sizeof(regex_t));
3574 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3575 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 }
3579
3580 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003581 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
3583 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3584 regex_t *preg;
3585 if (curproxy == &defproxy) {
3586 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003590 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003592
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 if (*(args[1]) == 0) {
3594 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
3598
3599 preg = calloc(1, sizeof(regex_t));
3600 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3601 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 }
3605
3606 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003607 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003609 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3610 regex_t *preg;
3611 if (curproxy == &defproxy) {
3612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003615 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003616 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003618
Willy Tarreaub8750a82006-09-03 09:56:00 +02003619 if (*(args[1]) == 0) {
3620 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003623 }
3624
3625 preg = calloc(1, sizeof(regex_t));
3626 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3627 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003630 }
3631
3632 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003633 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003634 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003635 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3636 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003637 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003641 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003642 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003644
Willy Tarreau977b8e42006-12-29 14:19:17 +01003645 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003646 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003650 }
3651
3652 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003653 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003654 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003657 }
3658
3659 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003660 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003661 }
3662 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3663 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003664 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003665 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003668 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003669 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003671
Willy Tarreau977b8e42006-12-29 14:19:17 +01003672 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003673 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003677 }
3678
3679 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003680 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003681 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 Tarreaua496b602006-12-17 23:15:24 +01003684 }
3685
3686 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003687 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
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 || *(args[2]) == 0) {
3700 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3701 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
3705
3706 preg = calloc(1, sizeof(regex_t));
3707 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3708 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 }
3712
3713 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3714 if (err) {
3715 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3716 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003720 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
3722 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3723 regex_t *preg;
3724 if (curproxy == &defproxy) {
3725 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003729 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003731
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 if (*(args[1]) == 0) {
3733 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
3737
3738 preg = calloc(1, sizeof(regex_t));
3739 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3740 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 }
3744
3745 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003746 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 }
3748 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3749 regex_t *preg;
3750 if (curproxy == &defproxy) {
3751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003755 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003757
Willy Tarreaubaaee002006-06-26 02:48:02 +02003758 if (*(args[1]) == 0) {
3759 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 }
3763
3764 preg = calloc(1, sizeof(regex_t));
3765 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3766 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 }
3770
3771 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003772 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 }
3774 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3775 regex_t *preg;
3776 if (curproxy == &defproxy) {
3777 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003781 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003783
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 if (*(args[1]) == 0) {
3785 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 }
3789
3790 preg = calloc(1, sizeof(regex_t));
3791 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3792 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 }
3796
3797 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003798 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 }
3800 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3801 regex_t *preg;
3802 if (curproxy == &defproxy) {
3803 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003807 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003809
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 if (*(args[1]) == 0) {
3811 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
3815
3816 preg = calloc(1, sizeof(regex_t));
3817 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3818 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 }
3822
3823 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003824 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003826 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3827 regex_t *preg;
3828 if (curproxy == &defproxy) {
3829 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003832 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003833 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003835
Willy Tarreaub8750a82006-09-03 09:56:00 +02003836 if (*(args[1]) == 0) {
3837 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003840 }
3841
3842 preg = calloc(1, sizeof(regex_t));
3843 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3844 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003847 }
3848
3849 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003850 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003853 struct wordlist *wl;
3854
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 if (curproxy == &defproxy) {
3856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003860 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 if (*(args[1]) == 0) {
3864 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003868
3869 wl = calloc(1, sizeof(*wl));
3870 wl->s = strdup(args[1]);
3871 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003872 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
3874 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3875 regex_t *preg;
3876
3877 if (*(args[1]) == 0 || *(args[2]) == 0) {
3878 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3879 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003883 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003885
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 preg = calloc(1, sizeof(regex_t));
3887 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3888 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 }
3892
3893 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3894 if (err) {
3895 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3896 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003900 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 }
3902 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3903 regex_t *preg;
3904 if (curproxy == &defproxy) {
3905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003908 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003909 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003911
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912 if (*(args[1]) == 0) {
3913 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916 }
3917
3918 preg = calloc(1, sizeof(regex_t));
3919 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3920 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923 }
3924
3925 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3926 if (err) {
3927 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3928 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
3932 }
3933 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3934 regex_t *preg;
3935 if (curproxy == &defproxy) {
3936 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003940 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003942
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 if (*(args[1]) == 0) {
3944 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 }
3948
3949 preg = calloc(1, sizeof(regex_t));
3950 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3951 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 }
3955
3956 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3957 if (err) {
3958 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3959 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 }
3963 }
3964 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3965 regex_t *preg;
3966 if (curproxy == &defproxy) {
3967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003971 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973
3974 if (*(args[1]) == 0 || *(args[2]) == 0) {
3975 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3976 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 }
3980
3981 preg = calloc(1, sizeof(regex_t));
3982 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3983 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 }
3987
3988 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3989 if (err) {
3990 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3991 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 }
3995 }
3996 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3997 regex_t *preg;
3998 if (curproxy == &defproxy) {
3999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004003 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004005
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 if (*(args[1]) == 0) {
4007 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 }
4011
4012 preg = calloc(1, sizeof(regex_t));
4013 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4014 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 }
4018
4019 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4020 if (err) {
4021 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4022 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 }
4026 }
4027 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
4028 regex_t *preg;
4029 if (curproxy == &defproxy) {
4030 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004034 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004036
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 if (*(args[1]) == 0) {
4038 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
4042
4043 preg = calloc(1, sizeof(regex_t));
4044 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4045 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 }
4049
4050 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4051 if (err) {
4052 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4053 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 }
4057 }
4058 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004059 struct wordlist *wl;
4060
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 if (curproxy == &defproxy) {
4062 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004066 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 if (*(args[1]) == 0) {
4070 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 }
4074
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004075 wl = calloc(1, sizeof(*wl));
4076 wl->s = strdup(args[1]);
4077 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 }
4079 else if (!strcmp(args[0], "errorloc") ||
4080 !strcmp(args[0], "errorloc302") ||
4081 !strcmp(args[0], "errorloc303")) { /* error location */
4082 int errnum, errlen;
4083 char *err;
4084
Willy Tarreau977b8e42006-12-29 14:19:17 +01004085 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004086 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004087
Willy Tarreaubaaee002006-06-26 02:48:02 +02004088 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004089 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
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 errnum = atol(args[1]);
4095 if (!strcmp(args[0], "errorloc303")) {
4096 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4097 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4098 } else {
4099 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4100 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4101 }
4102
Willy Tarreau0f772532006-12-23 20:51:41 +01004103 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4104 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004105 chunk_destroy(&curproxy->errmsg[rc]);
4106 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004107 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004109 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004110
4111 if (rc >= HTTP_ERR_SIZE) {
4112 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4113 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 free(err);
4115 }
4116 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004117 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4118 int errnum, errlen, fd;
4119 char *err;
4120 struct stat stat;
4121
4122 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004124
4125 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004126 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004129 }
4130
4131 fd = open(args[2], O_RDONLY);
4132 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4133 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4134 file, linenum, args[2], args[1]);
4135 if (fd >= 0)
4136 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004139 }
4140
Willy Tarreau27a674e2009-08-17 07:23:33 +02004141 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004142 errlen = stat.st_size;
4143 } else {
4144 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004145 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004147 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004148 }
4149
4150 err = malloc(errlen); /* malloc() must succeed during parsing */
4151 errnum = read(fd, err, errlen);
4152 if (errnum != errlen) {
4153 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4154 file, linenum, args[2], args[1]);
4155 close(fd);
4156 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004159 }
4160 close(fd);
4161
4162 errnum = atol(args[1]);
4163 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4164 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004165 chunk_destroy(&curproxy->errmsg[rc]);
4166 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004167 break;
4168 }
4169 }
4170
4171 if (rc >= HTTP_ERR_SIZE) {
4172 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4173 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004175 free(err);
4176 }
4177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004179 struct cfg_kw_list *kwl;
4180 int index;
4181
4182 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4183 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4184 if (kwl->kw[index].section != CFG_LISTEN)
4185 continue;
4186 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4187 /* prepare error message just in case */
4188 snprintf(trash, sizeof(trash),
4189 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004190 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4191 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004192 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004195 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004196 else if (rc > 0) {
4197 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004198 err_code |= ERR_WARN;
4199 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004200 }
Willy Tarreau93893792009-07-23 13:19:11 +02004201 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004202 }
4203 }
4204 }
4205
Willy Tarreau6daf3432008-01-22 16:44:08 +01004206 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 }
Willy Tarreau93893792009-07-23 13:19:11 +02004210 out:
4211 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212}
4213
4214
4215/*
4216 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004217 * Returns the error code, 0 if OK, or any combination of :
4218 * - ERR_ABORT: must abort ASAP
4219 * - ERR_FATAL: we can continue parsing but not start the service
4220 * - ERR_WARN: a warning has been emitted
4221 * - ERR_ALERT: an alert has been emitted
4222 * Only the two first ones can stop processing, the two others are just
4223 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004225int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004227 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 FILE *f;
4229 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004231 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 if ((f=fopen(file,"r")) == NULL)
4234 return -1;
4235
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004236 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004237 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004238 char *end;
4239 char *args[MAX_LINE_ARGS + 1];
4240 char *line = thisline;
4241
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 linenum++;
4243
4244 end = line + strlen(line);
4245
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004246 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4247 /* Check if we reached the limit and the last char is not \n.
4248 * Watch out for the last line without the terminating '\n'!
4249 */
4250 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004251 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004252 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004253 }
4254
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004256 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 line++;
4258
4259 arg = 0;
4260 args[arg] = line;
4261
4262 while (*line && arg < MAX_LINE_ARGS) {
4263 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4264 * C equivalent value. Other combinations left unchanged (eg: \1).
4265 */
4266 if (*line == '\\') {
4267 int skip = 0;
4268 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4269 *line = line[1];
4270 skip = 1;
4271 }
4272 else if (line[1] == 'r') {
4273 *line = '\r';
4274 skip = 1;
4275 }
4276 else if (line[1] == 'n') {
4277 *line = '\n';
4278 skip = 1;
4279 }
4280 else if (line[1] == 't') {
4281 *line = '\t';
4282 skip = 1;
4283 }
4284 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004285 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 unsigned char hex1, hex2;
4287 hex1 = toupper(line[2]) - '0';
4288 hex2 = toupper(line[3]) - '0';
4289 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4290 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4291 *line = (hex1<<4) + hex2;
4292 skip = 3;
4293 }
4294 else {
4295 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 }
4298 }
4299 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004300 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 end -= skip;
4302 }
4303 line++;
4304 }
4305 else if (*line == '#' || *line == '\n' || *line == '\r') {
4306 /* end of string, end of loop */
4307 *line = 0;
4308 break;
4309 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004310 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004312 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004313 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 line++;
4315 args[++arg] = line;
4316 }
4317 else {
4318 line++;
4319 }
4320 }
4321
4322 /* empty line */
4323 if (!**args)
4324 continue;
4325
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004326 if (*line) {
4327 /* we had to stop due to too many args.
4328 * Let's terminate the string, print the offending part then cut the
4329 * last arg.
4330 */
4331 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4332 line++;
4333 *line = '\0';
4334
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004335 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004336 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 args[arg] = line;
4339 }
4340
Willy Tarreau540abe42007-05-02 20:50:16 +02004341 /* zero out remaining args and ensure that at least one entry
4342 * is zeroed out.
4343 */
4344 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 args[arg] = line;
4346 }
4347
Willy Tarreau3842f002009-06-14 11:39:52 +02004348 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004349 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004350 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004351 for (arg=0; *args[arg+1]; arg++)
4352 args[arg] = args[arg+1]; // shift args after inversion
4353 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004354 else if (!strcmp(args[0], "default")) {
4355 kwm = KWM_DEF;
4356 for (arg=0; *args[arg+1]; arg++)
4357 args[arg] = args[arg+1]; // shift args after inversion
4358 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004359
Willy Tarreau3842f002009-06-14 11:39:52 +02004360 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4361 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004362 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004363 }
4364
Willy Tarreau977b8e42006-12-29 14:19:17 +01004365 if (!strcmp(args[0], "listen") ||
4366 !strcmp(args[0], "frontend") ||
4367 !strcmp(args[0], "backend") ||
4368 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004369 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004371 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004372 cursection = strdup(args[0]);
4373 }
4374 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004376 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004377 cursection = strdup(args[0]);
4378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004379 /* else it's a section keyword */
4380
4381 switch (confsect) {
4382 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 break;
4385 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004386 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 break;
4388 default:
4389 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004392
4393 if (err_code & ERR_ABORT)
4394 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004396 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004397 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004399 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004400}
4401
Willy Tarreaubb925012009-07-23 13:36:36 +02004402/*
4403 * Returns the error code, 0 if OK, or any combination of :
4404 * - ERR_ABORT: must abort ASAP
4405 * - ERR_FATAL: we can continue parsing but not start the service
4406 * - ERR_WARN: a warning has been emitted
4407 * - ERR_ALERT: an alert has been emitted
4408 * Only the two first ones can stop processing, the two others are just
4409 * indicators.
4410 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004411int check_config_validity()
4412{
4413 int cfgerr = 0;
4414 struct proxy *curproxy = NULL;
4415 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004416 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004417 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418
4419 /*
4420 * Now, check for the integrity of all that we have collected.
4421 */
4422
4423 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004424 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004426 /* first, we will invert the proxy list order */
4427 curproxy = NULL;
4428 while (proxy) {
4429 struct proxy *next;
4430
4431 next = proxy->next;
4432 proxy->next = curproxy;
4433 curproxy = proxy;
4434 if (!next)
4435 break;
4436 proxy = next;
4437 }
4438
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004440 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004441 err_code |= ERR_ALERT | ERR_FATAL;
4442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 }
4444
4445 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004446 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004447 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004448 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004449 unsigned int next_id;
4450
4451 if (!curproxy->uuid) {
4452 /* proxy ID not set, use automatic numbering with first
4453 * spare entry starting with next_pxid.
4454 */
4455 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4456 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4457 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4458 next_pxid++;
4459 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004460
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004462 /* ensure we don't keep listeners uselessly bound */
4463 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 curproxy = curproxy->next;
4465 continue;
4466 }
4467
Willy Tarreauff01a212009-03-15 13:46:16 +01004468 switch (curproxy->mode) {
4469 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004470 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004471 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004472 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4473 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004474 cfgerr++;
4475 }
4476
4477 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004478 Warning("config : servers will be ignored for %s '%s'.\n",
4479 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004480 break;
4481
4482 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004483 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004484 break;
4485
4486 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004487 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004488 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004489 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4490 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004491 cfgerr++;
4492 }
4493 break;
4494 }
4495
4496 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004497 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4498 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 cfgerr++;
4500 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004501
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004502 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004503 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004504 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004505 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4506 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004507 cfgerr++;
4508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004510 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004511 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4512 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004513 cfgerr++;
4514 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004516 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004517 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4518 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004519 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004520 }
4521 }
4522 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4523 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4524 /* If no LB algo is set in a backend, and we're not in
4525 * transparent mode, dispatch mode nor proxy mode, we
4526 * want to use balance roundrobin by default.
4527 */
4528 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4529 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 }
4531 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004532
Willy Tarreau82936582007-11-30 15:20:09 +01004533 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4534 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004535 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4536 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004537 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004538 }
4539
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004540 /* if a default backend was specified, let's find it */
4541 if (curproxy->defbe.name) {
4542 struct proxy *target;
4543
Alex Williams96532db2009-11-01 21:27:13 -05004544 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004545 if (!target) {
4546 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4547 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004548 cfgerr++;
4549 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004550 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4551 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004552 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004553 } else {
4554 free(curproxy->defbe.name);
4555 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004556 /* we force the backend to be present on at least all of
4557 * the frontend's processes.
4558 */
4559 target->bind_proc = curproxy->bind_proc ?
4560 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 }
4562 }
4563
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004564 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004565 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4566 /* map jump target for ACT_SETBE in req_rep chain */
4567 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004568 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004569 struct proxy *target;
4570
Willy Tarreaua496b602006-12-17 23:15:24 +01004571 if (exp->action != ACT_SETBE)
4572 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004573
Alex Williams96532db2009-11-01 21:27:13 -05004574 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004575 if (!target) {
4576 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4577 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004578 cfgerr++;
4579 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004580 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4581 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004582 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004583 } else {
4584 free((void *)exp->replace);
4585 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004586 /* we force the backend to be present on at least all of
4587 * the frontend's processes.
4588 */
4589 target->bind_proc = curproxy->bind_proc ?
4590 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004591 }
4592 }
4593 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004594
4595 /* find the target proxy for 'use_backend' rules */
4596 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004597 struct proxy *target;
4598
Alex Williams96532db2009-11-01 21:27:13 -05004599 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004600
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004601 if (!target) {
4602 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4603 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004604 cfgerr++;
4605 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004606 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4607 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004608 cfgerr++;
4609 } else {
4610 free((void *)rule->be.name);
4611 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004612 /* we force the backend to be present on at least all of
4613 * the frontend's processes.
4614 */
4615 target->bind_proc = curproxy->bind_proc ?
4616 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004617 }
4618 }
4619
Emeric Brunb982a3d2010-01-04 15:45:53 +01004620 /* find the target table for 'stick' rules */
4621 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4622 struct proxy *target;
4623
Emeric Brun1d33b292010-01-04 15:47:17 +01004624 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4625 if (mrule->flags & STK_IS_STORE)
4626 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4627
Emeric Brunb982a3d2010-01-04 15:45:53 +01004628 if (mrule->table.name)
4629 target = findproxy(mrule->table.name, PR_CAP_BE);
4630 else
4631 target = curproxy;
4632
4633 if (!target) {
4634 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4635 curproxy->id, mrule->table.name);
4636 cfgerr++;
4637 }
4638 else if (target->table.size == 0) {
4639 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4640 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4641 cfgerr++;
4642 }
4643 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4644 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4645 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4646 cfgerr++;
4647 }
4648 else {
4649 free((void *)mrule->table.name);
4650 mrule->table.t = &(target->table);
4651 }
4652 }
4653
4654 /* find the target table for 'store response' rules */
4655 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4656 struct proxy *target;
4657
Emeric Brun1d33b292010-01-04 15:47:17 +01004658 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4659
Emeric Brunb982a3d2010-01-04 15:45:53 +01004660 if (mrule->table.name)
4661 target = findproxy(mrule->table.name, PR_CAP_BE);
4662 else
4663 target = curproxy;
4664
4665 if (!target) {
4666 Alert("Proxy '%s': unable to find store table '%s'.\n",
4667 curproxy->id, mrule->table.name);
4668 cfgerr++;
4669 }
4670 else if (target->table.size == 0) {
4671 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4672 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4673 cfgerr++;
4674 }
4675 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4676 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4677 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4678 cfgerr++;
4679 }
4680 else {
4681 free((void *)mrule->table.name);
4682 mrule->table.t = &(target->table);
4683 }
4684 }
4685
Willy Tarreau2738a142006-07-08 17:28:09 +02004686 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004687 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004688 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004689 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004690 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004691 " | While not properly invalid, you will certainly encounter various problems\n"
4692 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004693 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004694 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004695 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004696 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004697
Willy Tarreau1fa31262007-12-03 00:36:16 +01004698 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4699 * We must still support older configurations, so let's find out whether those
4700 * parameters have been set or must be copied from contimeouts.
4701 */
4702 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004703 if (!curproxy->timeout.tarpit ||
4704 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004705 /* tarpit timeout not set. We search in the following order:
4706 * default.tarpit, curr.connect, default.connect.
4707 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004708 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004709 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004710 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004711 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004712 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004713 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004714 }
4715 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004716 (!curproxy->timeout.queue ||
4717 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004718 /* queue timeout not set. We search in the following order:
4719 * default.queue, curr.connect, default.connect.
4720 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004721 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004722 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004723 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004724 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004725 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004726 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004727 }
4728 }
4729
Willy Tarreauf3c69202006-07-09 16:42:34 +02004730 if (curproxy->options & PR_O_SSL3_CHK) {
4731 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4732 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4733 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4734 }
4735
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004736 /* The small pools required for the capture lists */
4737 if (curproxy->nb_req_cap)
4738 curproxy->req_cap_pool = create_pool("ptrcap",
4739 curproxy->nb_req_cap * sizeof(char *),
4740 MEM_F_SHARED);
4741 if (curproxy->nb_rsp_cap)
4742 curproxy->rsp_cap_pool = create_pool("ptrcap",
4743 curproxy->nb_rsp_cap * sizeof(char *),
4744 MEM_F_SHARED);
4745
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004746 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4747 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4748 MEM_F_SHARED);
4749
Willy Tarreau86034312006-12-29 00:10:33 +01004750 /* for backwards compatibility with "listen" instances, if
4751 * fullconn is not set but maxconn is set, then maxconn
4752 * is used.
4753 */
4754 if (!curproxy->fullconn)
4755 curproxy->fullconn = curproxy->maxconn;
4756
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 /* first, we will invert the servers list order */
4758 newsrv = NULL;
4759 while (curproxy->srv) {
4760 struct server *next;
4761
4762 next = curproxy->srv->next;
4763 curproxy->srv->next = newsrv;
4764 newsrv = curproxy->srv;
4765 if (!next)
4766 break;
4767 curproxy->srv = next;
4768 }
4769
Willy Tarreau20697042007-11-15 23:26:18 +01004770 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004771 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004773 /* We have to initialize the server lookup mechanism depending
4774 * on what LB algorithm was choosen.
4775 */
4776
4777 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4778 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4779 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004780 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4781 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4782 init_server_map(curproxy);
4783 } else {
4784 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4785 fwrr_init_server_groups(curproxy);
4786 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004787 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004788
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004789 case BE_LB_KIND_LC:
4790 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004791 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004792 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004793
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004794 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004795 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4796 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4797 chash_init_server_tree(curproxy);
4798 } else {
4799 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4800 init_server_map(curproxy);
4801 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004802 break;
4803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804
4805 if (curproxy->options & PR_O_LOGASAP)
4806 curproxy->to_log &= ~LW_BYTES;
4807
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004808 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4809 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4810 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4811 proxy_type_str(curproxy), curproxy->id);
4812 err_code |= ERR_WARN;
4813 }
4814
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004816 * ensure that we're not cross-dressing a TCP server into HTTP.
4817 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004818 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004819 newsrv = curproxy->srv;
4820 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004821 if (!newsrv->puid) {
4822 /* server ID not set, use automatic numbering with first
4823 * spare entry starting with next_svid.
4824 */
4825 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4826 newsrv->conf.id.key = newsrv->puid = next_id;
4827 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4828 next_id++;
4829 }
4830
Willy Tarreau21d2af32008-02-14 20:25:24 +01004831 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004832 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4833 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004834 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004835 }
4836 newsrv = newsrv->next;
4837 }
4838
4839 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 * If this server supports a maxconn parameter, it needs a dedicated
4841 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004842 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 */
4844 newsrv = curproxy->srv;
4845 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004846 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 /* Only 'minconn' was specified, or it was higher than or equal
4848 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4849 * this will avoid further useless expensive computations.
4850 */
4851 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004852 } else if (newsrv->maxconn && !newsrv->minconn) {
4853 /* minconn was not specified, so we set it to maxconn */
4854 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004855 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004856 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4857 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004858 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 }
4860
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004861 if (newsrv->trackit) {
4862 struct proxy *px;
4863 struct server *srv;
4864 char *pname, *sname;
4865
4866 pname = newsrv->trackit;
4867 sname = strrchr(pname, '/');
4868
4869 if (sname)
4870 *sname++ = '\0';
4871 else {
4872 sname = pname;
4873 pname = NULL;
4874 }
4875
4876 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004877 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004878 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004879 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4880 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004881 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004882 cfgerr++;
4883 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004884 }
4885 } else
4886 px = curproxy;
4887
4888 srv = findserver(px, sname);
4889 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004890 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4891 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004892 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004893 cfgerr++;
4894 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004895 }
4896
4897 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004898 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004899 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004900 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004901 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004902 cfgerr++;
4903 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004904 }
4905
4906 if (curproxy != px &&
4907 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004908 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004909 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004910 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004911 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004912 cfgerr++;
4913 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004914 }
4915
4916 newsrv->tracked = srv;
4917 newsrv->tracknext = srv->tracknext;
4918 srv->tracknext = newsrv;
4919
4920 free(newsrv->trackit);
4921 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004922 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 newsrv = newsrv->next;
4924 }
4925
Willy Tarreauc1a21672009-08-16 22:37:44 +02004926 if (curproxy->cap & PR_CAP_FE) {
4927 if (curproxy->tcp_req.inspect_delay ||
4928 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4929 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4930
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004931 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004932 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004933 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004934 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004935
4936 /* both TCP and HTTP must check switching rules */
4937 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4938 }
4939
4940 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004941 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004942 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004943 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004944 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004945
Emeric Brunb982a3d2010-01-04 15:45:53 +01004946 /* init table on backend capabilities proxy */
4947 stktable_init(&curproxy->table);
4948
Willy Tarreauc1a21672009-08-16 22:37:44 +02004949 /* If the backend does requires RDP cookie persistence, we have to
4950 * enable the corresponding analyser.
4951 */
4952 if (curproxy->options2 & PR_O2_RDPC_PRST)
4953 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4954 }
4955
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004956 listener = NULL;
4957 while (curproxy->listen) {
4958 struct listener *next;
4959
4960 next = curproxy->listen->next;
4961 curproxy->listen->next = listener;
4962 listener = curproxy->listen;
4963
4964 if (!next)
4965 break;
4966
4967 curproxy->listen = next;
4968 }
4969
Willy Tarreaue6b98942007-10-29 01:09:36 +01004970 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004971 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004972 listener = curproxy->listen;
4973 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004974 if (!listener->luid) {
4975 /* listener ID not set, use automatic numbering with first
4976 * spare entry starting with next_luid.
4977 */
4978 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4979 listener->conf.id.key = listener->luid = next_id;
4980 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4981 next_id++;
4982 }
4983
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004984 /* enable separate counters */
4985 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4986 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4987 if (!listener->name) {
4988 sprintf(trash, "sock-%d", listener->luid);
4989 listener->name = strdup(trash);
4990 }
4991 }
4992
Willy Tarreaue6b98942007-10-29 01:09:36 +01004993 if (curproxy->options & PR_O_TCP_NOLING)
4994 listener->options |= LI_O_NOLINGER;
4995 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004996 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004997 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004998 listener->accept = event_accept;
4999 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005000 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005001 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005002
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005003 /* smart accept mode is automatic in HTTP mode */
5004 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5005 (curproxy->mode == PR_MODE_HTTP &&
5006 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5007 listener->options |= LI_O_NOQUICKACK;
5008
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005009 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005010 listener = listener->next;
5011 }
5012
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 curproxy = curproxy->next;
5014 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005015
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005016 /*
5017 * Recount currently required checks.
5018 */
5019
5020 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5021 int optnum;
5022
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005023 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5024 if (curproxy->options & cfg_opts[optnum].val)
5025 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005026
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005027 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5028 if (curproxy->options2 & cfg_opts2[optnum].val)
5029 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005030 }
5031
Willy Tarreaubb925012009-07-23 13:36:36 +02005032 if (cfgerr > 0)
5033 err_code |= ERR_ALERT | ERR_FATAL;
5034 out:
5035 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036}
5037
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005038/*
5039 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5040 * parsing sessions.
5041 */
5042void cfg_register_keywords(struct cfg_kw_list *kwl)
5043{
5044 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5045}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005047/*
5048 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5049 */
5050void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5051{
5052 LIST_DEL(&kwl->list);
5053 LIST_INIT(&kwl->list);
5054}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055
5056/*
5057 * Local variables:
5058 * c-indent-level: 8
5059 * c-basic-offset: 8
5060 * End:
5061 */