blob: 9aae768ab255bde68e3113e0983928c417818661 [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 Tarreaue803de22010-01-21 17:43:04 +0100478 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
479 if (global.tune.client_rcvbuf != 0) {
480 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT;
482 goto out;
483 }
484 if (*(args[1]) == 0) {
485 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488 }
489 global.tune.client_rcvbuf = atol(args[1]);
490 }
491 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
492 if (global.tune.server_rcvbuf != 0) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.tune.server_rcvbuf = atol(args[1]);
503 }
504 else if (!strcmp(args[0], "tune.sndbuf.client")) {
505 if (global.tune.client_sndbuf != 0) {
506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
507 err_code |= ERR_ALERT;
508 goto out;
509 }
510 if (*(args[1]) == 0) {
511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
514 }
515 global.tune.client_sndbuf = atol(args[1]);
516 }
517 else if (!strcmp(args[0], "tune.sndbuf.server")) {
518 if (global.tune.server_sndbuf != 0) {
519 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
520 err_code |= ERR_ALERT;
521 goto out;
522 }
523 if (*(args[1]) == 0) {
524 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
527 }
528 global.tune.server_sndbuf = atol(args[1]);
529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530 else if (!strcmp(args[0], "uid")) {
531 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200532 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 }
541 global.uid = atol(args[1]);
542 }
543 else if (!strcmp(args[0], "gid")) {
544 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200545 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200553 }
554 global.gid = atol(args[1]);
555 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200556 /* user/group name handling */
557 else if (!strcmp(args[0], "user")) {
558 struct passwd *ha_user;
559 if (global.uid != 0) {
560 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200561 err_code |= ERR_ALERT;
562 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200563 }
564 errno = 0;
565 ha_user = getpwnam(args[1]);
566 if (ha_user != NULL) {
567 global.uid = (int)ha_user->pw_uid;
568 }
569 else {
570 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 +0200571 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200572 }
573 }
574 else if (!strcmp(args[0], "group")) {
575 struct group *ha_group;
576 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200577 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200580 }
581 errno = 0;
582 ha_group = getgrnam(args[1]);
583 if (ha_group != NULL) {
584 global.gid = (int)ha_group->gr_gid;
585 }
586 else {
587 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 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200589 }
590 }
591 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 else if (!strcmp(args[0], "nbproc")) {
593 if (global.nbproc != 0) {
594 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200595 err_code |= ERR_ALERT;
596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
603 global.nbproc = atol(args[1]);
604 }
605 else if (!strcmp(args[0], "maxconn")) {
606 if (global.maxconn != 0) {
607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT;
609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 }
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
616 global.maxconn = atol(args[1]);
617#ifdef SYSTEM_MAXCONN
618 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
619 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);
620 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623#endif /* SYSTEM_MAXCONN */
624 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100625 else if (!strcmp(args[0], "maxpipes")) {
626 if (global.maxpipes != 0) {
627 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT;
629 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100635 }
636 global.maxpipes = atol(args[1]);
637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 else if (!strcmp(args[0], "ulimit-n")) {
639 if (global.rlimit_nofile != 0) {
640 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200641 err_code |= ERR_ALERT;
642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 }
644 if (*(args[1]) == 0) {
645 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200646 err_code |= ERR_ALERT | ERR_FATAL;
647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 }
649 global.rlimit_nofile = atol(args[1]);
650 }
651 else if (!strcmp(args[0], "chroot")) {
652 if (global.chroot != NULL) {
653 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200654 err_code |= ERR_ALERT;
655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
662 global.chroot = strdup(args[1]);
663 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200664 else if (!strcmp(args[0], "description")) {
665 int i, len=0;
666 char *d;
667
668 if (!*args[1]) {
669 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
670 file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 for(i=1; *args[i]; i++)
676 len += strlen(args[i])+1;
677
678 if (global.desc)
679 free(global.desc);
680
681 global.desc = d = (char *)calloc(1, len);
682
683 d += sprintf(d, "%s", args[1]);
684 for(i=2; *args[i]; i++)
685 d += sprintf(d, " %s", args[i]);
686 }
687 else if (!strcmp(args[0], "node")) {
688 int i;
689 char c;
690
691 for (i=0; args[1][i]; i++) {
692 c = args[1][i];
693 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
694 break;
695 }
696
697 if (!i || args[1][i]) {
698 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
699 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
700 file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704
705 if (global.node)
706 free(global.node);
707
708 global.node = strdup(args[1]);
709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 else if (!strcmp(args[0], "pidfile")) {
711 if (global.pidfile != NULL) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT;
714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715 }
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 }
721 global.pidfile = strdup(args[1]);
722 }
723 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100724 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200725 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726
727 if (*(args[1]) == 0 || *(args[2]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732
733 facility = get_log_facility(args[2]);
734 if (facility < 0) {
735 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT | ERR_FATAL;
737 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739
740 level = 7; /* max syslog level = debug */
741 if (*(args[3])) {
742 level = get_log_level(args[3]);
743 if (level < 0) {
744 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT | ERR_FATAL;
746 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 }
749
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200750 minlvl = 0; /* limit syslog level to this level (emerg) */
751 if (*(args[4])) {
752 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200754 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200757 }
758 }
759
Robert Tsai81ae1952007-12-05 10:47:29 +0100760 if (args[1][0] == '/') {
761 logsrv.u.addr.sa_family = AF_UNIX;
762 logsrv.u.un = *str2sun(args[1]);
763 } else {
764 logsrv.u.addr.sa_family = AF_INET;
765 logsrv.u.in = *str2sa(args[1]);
766 if (!logsrv.u.in.sin_port)
767 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769
770 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100771 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 global.logfac1 = facility;
773 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200774 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100777 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 global.logfac2 = facility;
779 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200780 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 else {
783 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200784 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200786 }
787 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
788 if (global.spread_checks != 0) {
789 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200792 }
793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200797 }
798 global.spread_checks = atol(args[1]);
799 if (global.spread_checks < 0 || global.spread_checks > 50) {
800 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200801 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 }
804 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200805 struct cfg_kw_list *kwl;
806 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200807 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200808
809 list_for_each_entry(kwl, &cfg_keywords.list, list) {
810 for (index = 0; kwl->kw[index].kw != NULL; index++) {
811 if (kwl->kw[index].section != CFG_GLOBAL)
812 continue;
813 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
814 /* prepare error message just in case */
815 snprintf(trash, sizeof(trash),
816 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200817 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
818 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200819 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200821 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200822 else if (rc > 0) {
823 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_WARN;
825 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200826 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200827 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200828 }
829 }
830 }
831
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200833 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200835
Willy Tarreau058e9072009-07-20 09:30:05 +0200836 out:
837 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838}
839
Willy Tarreau97cb7802010-01-03 20:23:58 +0100840/* Perform the most basic initialization of a proxy :
841 * memset(), list_init(*), reset_timeouts(*).
842 */
843static void init_new_proxy(struct proxy *p)
844{
845 memset(p, 0, sizeof(struct proxy));
846 LIST_INIT(&p->pendconns);
847 LIST_INIT(&p->acl);
848 LIST_INIT(&p->block_cond);
849 LIST_INIT(&p->redirect_rules);
850 LIST_INIT(&p->mon_fail_cond);
851 LIST_INIT(&p->switching_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100852 LIST_INIT(&p->sticking_rules);
853 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100854 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100855 LIST_INIT(&p->req_add);
856 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100857
858 /* Timeouts are defined as -1 */
859 proxy_reset_timeouts(p);
860}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200862void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100864 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200865 defproxy.mode = PR_MODE_TCP;
866 defproxy.state = PR_STNEW;
867 defproxy.maxconn = cfg_maxpconn;
868 defproxy.conn_retries = CONN_RETRIES;
869 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100870
871 defproxy.defsrv.inter = DEF_CHKINTR;
872 defproxy.defsrv.fastinter = 0;
873 defproxy.defsrv.downinter = 0;
874 defproxy.defsrv.rise = DEF_RISETIME;
875 defproxy.defsrv.fall = DEF_FALLTIME;
876 defproxy.defsrv.check_port = 0;
877 defproxy.defsrv.maxqueue = 0;
878 defproxy.defsrv.minconn = 0;
879 defproxy.defsrv.maxconn = 0;
880 defproxy.defsrv.slowstart = 0;
881 defproxy.defsrv.onerror = DEF_HANA_ONERR;
882 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
883 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884}
885
886/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100887 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200888 * Returns the error code, 0 if OK, or any combination of :
889 * - ERR_ABORT: must abort ASAP
890 * - ERR_FATAL: we can continue parsing but not start the service
891 * - ERR_WARN: a warning has been emitted
892 * - ERR_ALERT: an alert has been emitted
893 * Only the two first ones can stop processing, the two others are just
894 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200896int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897{
898 static struct proxy *curproxy = NULL;
899 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200900 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100901 int rc;
902 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200903 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904
Willy Tarreau977b8e42006-12-29 14:19:17 +0100905 if (!strcmp(args[0], "listen"))
906 rc = PR_CAP_LISTEN;
907 else if (!strcmp(args[0], "frontend"))
908 rc = PR_CAP_FE | PR_CAP_RS;
909 else if (!strcmp(args[0], "backend"))
910 rc = PR_CAP_BE | PR_CAP_RS;
911 else if (!strcmp(args[0], "ruleset"))
912 rc = PR_CAP_RS;
913 else
914 rc = PR_CAP_NONE;
915
916 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 if (!*args[1]) {
918 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
919 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200921 err_code |= ERR_ALERT | ERR_ABORT;
922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200924
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100925 err = invalid_char(args[1]);
926 if (err) {
927 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
928 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200929 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100930 }
931
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200932 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
933 /*
934 * If there are two proxies with the same name only following
935 * combinations are allowed:
936 *
937 * listen backend frontend ruleset
938 * listen - - - -
939 * backend - - OK -
940 * frontend - OK - -
941 * ruleset - - - -
942 */
943
944 if (!strcmp(curproxy->id, args[1]) &&
945 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
946 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200947 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
948 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
949 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200950 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200951 }
952 }
953
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
955 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200956 err_code |= ERR_ALERT | ERR_ABORT;
957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100959
Willy Tarreau97cb7802010-01-03 20:23:58 +0100960 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 curproxy->next = proxy;
962 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200963 curproxy->conf.file = file;
964 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200965 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100967 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968
969 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100970 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200971 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200972 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200973 err_code |= ERR_FATAL;
974 goto out;
975 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200976 new = curproxy->listen;
977 while (new != last) {
978 new->conf.file = file;
979 new->conf.line = linenum;
980 new = new->next;
981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 global.maxsock++;
983 }
984
985 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100986 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
987
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100990 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200991 curproxy->no_options = defproxy.no_options;
992 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100993 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100994 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200995 curproxy->except_net = defproxy.except_net;
996 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200997 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200998 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001000 if (defproxy.fwdfor_hdr_len) {
1001 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1002 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1003 }
1004
Willy Tarreaub86db342009-11-30 11:50:16 +01001005 if (defproxy.orgto_hdr_len) {
1006 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1007 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1008 }
1009
Willy Tarreau977b8e42006-12-29 14:19:17 +01001010 if (curproxy->cap & PR_CAP_FE) {
1011 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001012 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001013 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001014
1015 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001016 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1017 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001018
1019 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 if (curproxy->cap & PR_CAP_BE) {
1023 curproxy->fullconn = defproxy.fullconn;
1024 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025
Willy Tarreau977b8e42006-12-29 14:19:17 +01001026 if (defproxy.check_req)
1027 curproxy->check_req = strdup(defproxy.check_req);
1028 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029
Willy Tarreau977b8e42006-12-29 14:19:17 +01001030 if (defproxy.cookie_name)
1031 curproxy->cookie_name = strdup(defproxy.cookie_name);
1032 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001033 if (defproxy.cookie_domain)
1034 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001035
Emeric Brun647caf12009-06-30 17:57:00 +02001036 if (defproxy.rdp_cookie_name)
1037 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1038 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1039
Willy Tarreau01732802007-11-01 22:48:15 +01001040 if (defproxy.url_param_name)
1041 curproxy->url_param_name = strdup(defproxy.url_param_name);
1042 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001043
Benoitaffb4812009-03-25 13:02:10 +01001044 if (defproxy.hh_name)
1045 curproxy->hh_name = strdup(defproxy.hh_name);
1046 curproxy->hh_len = defproxy.hh_len;
1047 curproxy->hh_match_domain = defproxy.hh_match_domain;
1048
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001049 if (defproxy.iface_name)
1050 curproxy->iface_name = strdup(defproxy.iface_name);
1051 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001054 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001055 if (defproxy.capture_name)
1056 curproxy->capture_name = strdup(defproxy.capture_name);
1057 curproxy->capture_namelen = defproxy.capture_namelen;
1058 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060
Willy Tarreau977b8e42006-12-29 14:19:17 +01001061 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001062 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001063 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001064 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001065 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001066 curproxy->uri_auth = defproxy.uri_auth;
1067 curproxy->mon_net = defproxy.mon_net;
1068 curproxy->mon_mask = defproxy.mon_mask;
1069 if (defproxy.monitor_uri)
1070 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1071 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001072 if (defproxy.defbe.name)
1073 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001074 }
1075
1076 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001077 curproxy->timeout.connect = defproxy.timeout.connect;
1078 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001079 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001080 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001081 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001082 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001083 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001084 curproxy->source_addr = defproxy.source_addr;
1085 }
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 curproxy->mode = defproxy.mode;
1088 curproxy->logfac1 = defproxy.logfac1;
1089 curproxy->logsrv1 = defproxy.logsrv1;
1090 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001091 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 curproxy->logfac2 = defproxy.logfac2;
1093 curproxy->logsrv2 = defproxy.logsrv2;
1094 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001095 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001097 curproxy->conf.used_listener_id = EB_ROOT;
1098 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001099
Willy Tarreau93893792009-07-23 13:19:11 +02001100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 }
1102 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1103 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001104 /* FIXME-20070101: we should do this too at the end of the
1105 * config parsing to free all default values.
1106 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001107 free(defproxy.check_req);
1108 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001109 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001110 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001111 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001112 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001113 free(defproxy.capture_name);
1114 free(defproxy.monitor_uri);
1115 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001116 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001117 free(defproxy.fwdfor_hdr_name);
1118 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001119 free(defproxy.orgto_hdr_name);
1120 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001121
Willy Tarreaua534fea2008-08-03 12:19:50 +02001122 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001123 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 /* we cannot free uri_auth because it might already be used */
1126 init_default_instance();
1127 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001128 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 else if (curproxy == NULL) {
1132 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136
Willy Tarreau977b8e42006-12-29 14:19:17 +01001137
1138 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001140 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001141 int cur_arg;
1142
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 if (curproxy == &defproxy) {
1144 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001148 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001149 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150
1151 if (strchr(args[1], ':') == NULL) {
1152 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001157
1158 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001159 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto out;
1162 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001163
Willy Tarreau90a570f2009-10-04 20:54:54 +02001164 new_listen = curproxy->listen;
1165 while (new_listen != last_listen) {
1166 new_listen->conf.file = file;
1167 new_listen->conf.line = linenum;
1168 new_listen = new_listen->next;
1169 }
1170
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001171 cur_arg = 2;
1172 while (*(args[cur_arg])) {
1173 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1174#ifdef SO_BINDTODEVICE
1175 struct listener *l;
1176
1177 if (!*args[cur_arg + 1]) {
1178 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1179 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001182 }
1183
1184 for (l = curproxy->listen; l != last_listen; l = l->next)
1185 l->interface = strdup(args[cur_arg + 1]);
1186
1187 global.last_checks |= LSTCHK_NETADM;
1188
1189 cur_arg += 2;
1190 continue;
1191#else
1192 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1193 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001194 err_code |= ERR_ALERT | ERR_FATAL;
1195 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001196#endif
1197 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001198 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1199#ifdef TCP_MAXSEG
1200 struct listener *l;
1201 int mss;
1202
1203 if (!*args[cur_arg + 1]) {
1204 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001208 }
1209
1210 mss = str2uic(args[cur_arg + 1]);
1211 if (mss < 1 || mss > 65535) {
1212 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001216 }
1217
1218 for (l = curproxy->listen; l != last_listen; l = l->next)
1219 l->maxseg = mss;
1220
1221 cur_arg += 2;
1222 continue;
1223#else
1224 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1225 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001228#endif
1229 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001230
1231 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1232#ifdef TCP_DEFER_ACCEPT
1233 struct listener *l;
1234
1235 for (l = curproxy->listen; l != last_listen; l = l->next)
1236 l->options |= LI_O_DEF_ACCEPT;
1237
1238 cur_arg ++;
1239 continue;
1240#else
1241 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1242 file, linenum, args[0], args[cur_arg]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245#endif
1246 }
1247
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001248 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001249#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001250 struct listener *l;
1251
1252 for (l = curproxy->listen; l != last_listen; l = l->next)
1253 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001254
1255 cur_arg ++;
1256 continue;
1257#else
1258 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1259 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001262#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001263 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001264
1265 if (!strcmp(args[cur_arg], "name")) {
1266 struct listener *l;
1267
1268 for (l = curproxy->listen; l != last_listen; l = l->next)
1269 l->name = strdup(args[cur_arg + 1]);
1270
1271 cur_arg += 2;
1272 continue;
1273 }
1274
1275 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001276 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001277 struct listener *l;
1278
1279 if (curproxy->listen->next != last_listen) {
1280 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1281 file, linenum, args[cur_arg]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285
1286 if (!*args[cur_arg + 1]) {
1287 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1288 file, linenum, args[cur_arg]);
1289 err_code |= ERR_ALERT | ERR_FATAL;
1290 goto out;
1291 }
1292
1293 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001294 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001295
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001296 if (curproxy->listen->luid <= 0) {
1297 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001298 file, linenum);
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
1302
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001303 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1304 if (node) {
1305 l = container_of(node, struct listener, conf.id);
1306 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1307 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
1310 }
1311 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1312
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001313 cur_arg += 2;
1314 continue;
1315 }
1316
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001317 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 +01001318 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 }
1325 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1326 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1327 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1328 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001331 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001332 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001333 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001334
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335 /* flush useless bits */
1336 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001339 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001340 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001341 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001342
Willy Tarreau1c47f852006-07-09 08:22:27 +02001343 if (!*args[1]) {
1344 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001348 }
1349
Willy Tarreaua534fea2008-08-03 12:19:50 +02001350 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001351 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001352 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001353 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001354 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1355
Willy Tarreau93893792009-07-23 13:19:11 +02001356 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1359 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1360 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1361 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1362 else {
1363 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 }
1367 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001368 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001369 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001370
1371 if (curproxy == &defproxy) {
1372 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001376 }
1377
1378 if (!*args[1]) {
1379 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001383 }
1384
1385 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001386 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001387
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001388 if (curproxy->uuid <= 0) {
1389 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001390 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
1392 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001393 }
1394
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001395 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1396 if (node) {
1397 struct proxy *target = container_of(node, struct proxy, conf.id);
1398 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1399 file, linenum, proxy_type_str(curproxy), curproxy->id,
1400 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1401 err_code |= ERR_ALERT | ERR_FATAL;
1402 goto out;
1403 }
1404 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001405 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406 else if (!strcmp(args[0], "description")) {
1407 int i, len=0;
1408 char *d;
1409
1410 if (!*args[1]) {
1411 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1412 file, linenum, args[0]);
1413 return -1;
1414 }
1415
1416 for(i=1; *args[i]; i++)
1417 len += strlen(args[i])+1;
1418
1419 d = (char *)calloc(1, len);
1420 curproxy->desc = d;
1421
1422 d += sprintf(d, "%s", args[1]);
1423 for(i=2; *args[i]; i++)
1424 d += sprintf(d, " %s", args[i]);
1425
1426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1428 curproxy->state = PR_STSTOPPED;
1429 }
1430 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1431 curproxy->state = PR_STNEW;
1432 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001433 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1434 int cur_arg = 1;
1435 unsigned int set = 0;
1436
1437 while (*args[cur_arg]) {
1438 int u;
1439 if (strcmp(args[cur_arg], "all") == 0) {
1440 set = 0;
1441 break;
1442 }
1443 else if (strcmp(args[cur_arg], "odd") == 0) {
1444 set |= 0x55555555;
1445 }
1446 else if (strcmp(args[cur_arg], "even") == 0) {
1447 set |= 0xAAAAAAAA;
1448 }
1449 else {
1450 u = str2uic(args[cur_arg]);
1451 if (u < 1 || u > 32) {
1452 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1453 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001456 }
1457 if (u > global.nbproc) {
1458 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1459 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001460 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001461 }
1462 set |= 1 << (u - 1);
1463 }
1464 cur_arg++;
1465 }
1466 curproxy->bind_proc = set;
1467 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001468 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001469 if (curproxy == &defproxy) {
1470 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001471 err_code |= ERR_ALERT | ERR_FATAL;
1472 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001473 }
1474
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001475 err = invalid_char(args[1]);
1476 if (err) {
1477 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1478 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001479 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001480 }
1481
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001482 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1483 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1484 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001485 err_code |= ERR_ALERT | ERR_FATAL;
1486 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001487 }
1488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1490 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001493 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 if (*(args[1]) == 0) {
1496 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001501
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001502 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001503 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 curproxy->cookie_name = strdup(args[1]);
1505 curproxy->cookie_len = strlen(curproxy->cookie_name);
1506
1507 cur_arg = 2;
1508 while (*(args[cur_arg])) {
1509 if (!strcmp(args[cur_arg], "rewrite")) {
1510 curproxy->options |= PR_O_COOK_RW;
1511 }
1512 else if (!strcmp(args[cur_arg], "indirect")) {
1513 curproxy->options |= PR_O_COOK_IND;
1514 }
1515 else if (!strcmp(args[cur_arg], "insert")) {
1516 curproxy->options |= PR_O_COOK_INS;
1517 }
1518 else if (!strcmp(args[cur_arg], "nocache")) {
1519 curproxy->options |= PR_O_COOK_NOC;
1520 }
1521 else if (!strcmp(args[cur_arg], "postonly")) {
1522 curproxy->options |= PR_O_COOK_POST;
1523 }
1524 else if (!strcmp(args[cur_arg], "prefix")) {
1525 curproxy->options |= PR_O_COOK_PFX;
1526 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001527 else if (!strcmp(args[cur_arg], "domain")) {
1528 if (!*args[cur_arg + 1]) {
1529 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1530 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001533 }
1534
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001535 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001536 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001537 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1538 " dots nor does not start with a dot."
1539 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001540 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001541 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001542 }
1543
1544 err = invalid_domainchar(args[cur_arg + 1]);
1545 if (err) {
1546 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1547 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001550 }
1551
Willy Tarreau68a897b2009-12-03 23:28:34 +01001552 if (!curproxy->cookie_domain) {
1553 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1554 } else {
1555 /* one domain was already specified, add another one by
1556 * building the string which will be returned along with
1557 * the cookie.
1558 */
1559 char *new_ptr;
1560 int new_len = strlen(curproxy->cookie_domain) +
1561 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1562 new_ptr = malloc(new_len);
1563 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1564 free(curproxy->cookie_domain);
1565 curproxy->cookie_domain = new_ptr;
1566 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001567 cur_arg++;
1568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001570 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001572 err_code |= ERR_ALERT | ERR_FATAL;
1573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 }
1575 cur_arg++;
1576 }
1577 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1578 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1579 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001580 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 }
1582
1583 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1584 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
1588 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001589 else if (!strcmp(args[0], "persist")) { /* persist */
1590 if (*(args[1]) == 0) {
1591 Alert("parsing [%s:%d] : missing persist method.\n",
1592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001595 }
1596
1597 if (!strncmp(args[1], "rdp-cookie", 10)) {
1598 curproxy->options2 |= PR_O2_RDPC_PRST;
1599
Emeric Brunb982a3d2010-01-04 15:45:53 +01001600 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001601 const char *beg, *end;
1602
1603 beg = args[1] + 11;
1604 end = strchr(beg, ')');
1605
1606 if (!end || end == beg) {
1607 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1608 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001609 err_code |= ERR_ALERT | ERR_FATAL;
1610 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001611 }
1612
1613 free(curproxy->rdp_cookie_name);
1614 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1615 curproxy->rdp_cookie_len = end-beg;
1616 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001617 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001618 free(curproxy->rdp_cookie_name);
1619 curproxy->rdp_cookie_name = strdup("msts");
1620 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1621 }
1622 else { /* syntax */
1623 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1624 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001627 }
1628 }
1629 else {
1630 Alert("parsing [%s:%d] : unknown persist method.\n",
1631 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_ALERT | ERR_FATAL;
1633 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001634 }
1635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001637 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001639 if (curproxy == &defproxy) {
1640 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
1643 }
1644
Willy Tarreau977b8e42006-12-29 14:19:17 +01001645 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001646 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001647
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001649 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 }
1654 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001655 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 curproxy->appsession_name = strdup(args[1]);
1657 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1658 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001659 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1660 if (err) {
1661 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1662 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001665 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001666 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001667
Willy Tarreau51041c72007-09-09 21:56:53 +02001668 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1669 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_ABORT;
1671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001673
1674 cur_arg = 6;
1675 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001676 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1677 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001678 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001679 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001680 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001681 } else if (!strcmp(args[cur_arg], "prefix")) {
1682 curproxy->options2 |= PR_O2_AS_PFX;
1683 } else if (!strcmp(args[cur_arg], "mode")) {
1684 if (!*args[cur_arg + 1]) {
1685 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1686 file, linenum, args[0], args[cur_arg]);
1687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
1689 }
1690
1691 cur_arg++;
1692 if (!strcmp(args[cur_arg], "query-string")) {
1693 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1694 curproxy->options2 |= PR_O2_AS_M_QS;
1695 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1696 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1697 curproxy->options2 |= PR_O2_AS_M_PP;
1698 } else {
1699 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001704 cur_arg++;
1705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 } /* Url App Session */
1707 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001708 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001709 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001710
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 if (*(args[4]) == 0) {
1713 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001718 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 curproxy->capture_name = strdup(args[2]);
1720 curproxy->capture_namelen = strlen(curproxy->capture_name);
1721 curproxy->capture_len = atol(args[4]);
1722 if (curproxy->capture_len >= CAPTURE_LEN) {
1723 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1724 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 curproxy->capture_len = CAPTURE_LEN - 1;
1727 }
1728 curproxy->to_log |= LW_COOKIE;
1729 }
1730 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1731 struct cap_hdr *hdr;
1732
1733 if (curproxy == &defproxy) {
1734 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 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 }
1738
1739 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1740 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1741 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 }
1745
1746 hdr = calloc(sizeof(struct cap_hdr), 1);
1747 hdr->next = curproxy->req_cap;
1748 hdr->name = strdup(args[3]);
1749 hdr->namelen = strlen(args[3]);
1750 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001751 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 hdr->index = curproxy->nb_req_cap++;
1753 curproxy->req_cap = hdr;
1754 curproxy->to_log |= LW_REQHDR;
1755 }
1756 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1757 struct cap_hdr *hdr;
1758
1759 if (curproxy == &defproxy) {
1760 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 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 }
1764
1765 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1766 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1767 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001768 err_code |= ERR_ALERT | ERR_FATAL;
1769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 }
1771 hdr = calloc(sizeof(struct cap_hdr), 1);
1772 hdr->next = curproxy->rsp_cap;
1773 hdr->name = strdup(args[3]);
1774 hdr->namelen = strlen(args[3]);
1775 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001776 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 hdr->index = curproxy->nb_rsp_cap++;
1778 curproxy->rsp_cap = hdr;
1779 curproxy->to_log |= LW_RSPHDR;
1780 }
1781 else {
1782 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1783 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 }
1787 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 if (*(args[1]) == 0) {
1793 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1794 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_FATAL;
1796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
1798 curproxy->conn_retries = atol(args[1]);
1799 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001800 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1801 int pol = ACL_COND_NONE;
1802 struct acl_cond *cond;
1803
Willy Tarreaub099aca2008-10-12 17:26:37 +02001804 if (curproxy == &defproxy) {
1805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001806 err_code |= ERR_ALERT | ERR_FATAL;
1807 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001808 }
1809
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001810 if (!strcmp(args[1], "if"))
1811 pol = ACL_COND_IF;
1812 else if (!strcmp(args[1], "unless"))
1813 pol = ACL_COND_UNLESS;
1814
1815 if (pol == ACL_COND_NONE) {
1816 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1817 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001820 }
1821
1822 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1823 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1824 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001827 }
Willy Tarreau88922352009-10-04 22:02:50 +02001828 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001829 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001830 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001831 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001832 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001833 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001834 else if (!strcmp(args[0], "redirect")) {
1835 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001836 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001837 struct redirect_rule *rule;
1838 int cur_arg;
1839 int type = REDIRECT_TYPE_NONE;
1840 int code = 302;
1841 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001842 char *cookie = NULL;
1843 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001844 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001845
1846 cur_arg = 1;
1847 while (*(args[cur_arg])) {
1848 if (!strcmp(args[cur_arg], "location")) {
1849 if (!*args[cur_arg + 1]) {
1850 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1851 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001854 }
1855
1856 type = REDIRECT_TYPE_LOCATION;
1857 cur_arg++;
1858 destination = args[cur_arg];
1859 }
1860 else if (!strcmp(args[cur_arg], "prefix")) {
1861 if (!*args[cur_arg + 1]) {
1862 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1863 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001864 err_code |= ERR_ALERT | ERR_FATAL;
1865 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001866 }
1867
1868 type = REDIRECT_TYPE_PREFIX;
1869 cur_arg++;
1870 destination = args[cur_arg];
1871 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001872 else if (!strcmp(args[cur_arg], "set-cookie")) {
1873 if (!*args[cur_arg + 1]) {
1874 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1875 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001878 }
1879
1880 cur_arg++;
1881 cookie = args[cur_arg];
1882 cookie_set = 1;
1883 }
1884 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1885 if (!*args[cur_arg + 1]) {
1886 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1887 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001890 }
1891
1892 cur_arg++;
1893 cookie = args[cur_arg];
1894 cookie_set = 0;
1895 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001896 else if (!strcmp(args[cur_arg],"code")) {
1897 if (!*args[cur_arg + 1]) {
1898 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1899 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001900 err_code |= ERR_ALERT | ERR_FATAL;
1901 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001902 }
1903 cur_arg++;
1904 code = atol(args[cur_arg]);
1905 if (code < 301 || code > 303) {
1906 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1907 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001910 }
1911 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001912 else if (!strcmp(args[cur_arg],"drop-query")) {
1913 flags |= REDIRECT_FLAG_DROP_QS;
1914 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001915 else if (!strcmp(args[cur_arg],"append-slash")) {
1916 flags |= REDIRECT_FLAG_APPEND_SLASH;
1917 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001918 else if (!strcmp(args[cur_arg], "if")) {
1919 pol = ACL_COND_IF;
1920 cur_arg++;
1921 break;
1922 }
1923 else if (!strcmp(args[cur_arg], "unless")) {
1924 pol = ACL_COND_UNLESS;
1925 cur_arg++;
1926 break;
1927 }
1928 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001929 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 +02001930 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001933 }
1934 cur_arg++;
1935 }
1936
1937 if (type == REDIRECT_TYPE_NONE) {
1938 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001942 }
1943
Willy Tarreauf285f542010-01-03 20:03:03 +01001944 if (pol != ACL_COND_NONE &&
1945 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001946 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001950 }
1951
Willy Tarreauf285f542010-01-03 20:03:03 +01001952 if (cond) {
1953 cond->file = file;
1954 cond->line = linenum;
1955 curproxy->acl_requires |= cond->requires;
1956 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001957 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1958 rule->cond = cond;
1959 rule->rdr_str = strdup(destination);
1960 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001961 if (cookie) {
1962 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1963 * a clear consists in appending "; Max-Age=0" at the end.
1964 */
1965 rule->cookie_len = strlen(cookie);
1966 if (cookie_set)
1967 rule->cookie_str = strdup(cookie);
1968 else {
1969 rule->cookie_str = malloc(rule->cookie_len + 12);
1970 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1971 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1972 rule->cookie_len += 11;
1973 }
1974 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001975 rule->type = type;
1976 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001977 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001978 LIST_INIT(&rule->list);
1979 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001980 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001981 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001982 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001983 int pol = ACL_COND_NONE;
1984 struct acl_cond *cond;
1985 struct switching_rule *rule;
1986
Willy Tarreaub099aca2008-10-12 17:26:37 +02001987 if (curproxy == &defproxy) {
1988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001991 }
1992
Willy Tarreau55ea7572007-06-17 19:56:27 +02001993 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001994 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001995
1996 if (*(args[1]) == 0) {
1997 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002000 }
2001
2002 if (!strcmp(args[2], "if"))
2003 pol = ACL_COND_IF;
2004 else if (!strcmp(args[2], "unless"))
2005 pol = ACL_COND_UNLESS;
2006
2007 if (pol == ACL_COND_NONE) {
2008 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2009 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002012 }
2013
2014 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002015 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002016 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002019 }
2020
Willy Tarreau88922352009-10-04 22:02:50 +02002021 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002022 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002023 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02002024 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02002025 struct acl *acl;
2026 const char *name;
2027
2028 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2029 name = acl ? acl->name : "(unknown)";
2030 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
2031 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02002033 }
2034
Willy Tarreau55ea7572007-06-17 19:56:27 +02002035 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2036 rule->cond = cond;
2037 rule->be.name = strdup(args[1]);
2038 LIST_INIT(&rule->list);
2039 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2040 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002041 else if (!strcmp(args[0], "stick-table")) {
2042 int myidx = 1;
2043
2044 curproxy->table.type = (unsigned int)-1;
2045 while (*args[myidx]) {
2046 const char *err;
2047
2048 if (strcmp(args[myidx], "size") == 0) {
2049 myidx++;
2050 if (!*(args[myidx])) {
2051 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2052 file, linenum, args[myidx-1]);
2053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
2055 }
2056 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2057 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2058 file, linenum, *err, args[myidx-1]);
2059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
2061 }
2062 }
2063 else if (strcmp(args[myidx], "expire") == 0) {
2064 myidx++;
2065 if (!*(args[myidx])) {
2066 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2067 file, linenum, args[myidx-1]);
2068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
2070 }
2071 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2072 if (err) {
2073 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2074 file, linenum, *err, args[myidx-1]);
2075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
2077 }
2078 curproxy->table.expire = val;
2079 }
2080 else if (strcmp(args[myidx], "nopurge") == 0) {
2081 curproxy->table.nopurge = 1;
2082 }
2083 else if (strcmp(args[myidx], "type") == 0) {
2084 myidx++;
2085 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2086 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2087 file, linenum, args[myidx]);
2088 err_code |= ERR_ALERT | ERR_FATAL;
2089 goto out;
2090 }
2091 }
2092 myidx++;
2093 }
2094
2095 if (!curproxy->table.size) {
2096 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2097 file, linenum);
2098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
2100 }
2101
2102 if (curproxy->table.type == (unsigned int)-1) {
2103 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2104 file, linenum);
2105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
2107 }
2108 }
2109 else if (!strcmp(args[0], "stick")) {
2110 int pol = ACL_COND_NONE;
2111 struct acl_cond *cond = NULL;
2112 struct sticking_rule *rule;
2113 struct pattern_expr *expr;
2114 int myidx = 0;
2115 const char *name = NULL;
2116 int flags;
2117
2118 if (curproxy == &defproxy) {
2119 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
2123
2124 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2125 err_code |= ERR_WARN;
2126 goto out;
2127 }
2128
2129 myidx++;
2130 if ((strcmp(args[myidx], "store") == 0) ||
2131 (strcmp(args[myidx], "store-request") == 0)) {
2132 myidx++;
2133 flags = STK_IS_STORE;
2134 }
2135 else if (strcmp(args[myidx], "store-response") == 0) {
2136 myidx++;
2137 flags = STK_IS_STORE | STK_ON_RSP;
2138 }
2139 else if (strcmp(args[myidx], "match") == 0) {
2140 myidx++;
2141 flags = STK_IS_MATCH;
2142 }
2143 else if (strcmp(args[myidx], "on") == 0) {
2144 myidx++;
2145 flags = STK_IS_MATCH | STK_IS_STORE;
2146 }
2147 else {
2148 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
2151 }
2152
2153 if (*(args[myidx]) == 0) {
2154 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158
2159 expr = pattern_parse_expr(args, &myidx);
2160 if (!expr) {
2161 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
2164 }
2165
2166 if (flags & STK_ON_RSP) {
2167 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2168 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2169 file, linenum, args[0], expr->fetch->kw);
2170 err_code |= ERR_ALERT | ERR_FATAL;
2171 goto out;
2172 }
2173 } else {
2174 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2175 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2176 file, linenum, args[0], expr->fetch->kw);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180 }
2181
2182 if (strcmp(args[myidx], "table") == 0) {
2183 myidx++;
2184 name = args[myidx++];
2185 }
2186
2187 if (*(args[myidx]) == 0)
2188 pol = ACL_COND_NONE;
2189 else if (strcmp(args[myidx], "if") == 0)
2190 pol = ACL_COND_IF;
2191 else if (strcmp(args[myidx], "unless") == 0)
2192 pol = ACL_COND_UNLESS;
2193 else {
2194 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2195 file, linenum, args[0], args[myidx]);
2196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
2198 }
2199
2200 if (pol != ACL_COND_NONE) {
2201 myidx++;
2202 if ((cond = parse_acl_cond((const char **)args + myidx, &curproxy->acl, pol)) == NULL) {
2203 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2204 file, linenum, args[0]);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208
2209 cond->file = file;
2210 cond->line = linenum;
2211 curproxy->acl_requires |= cond->requires;
2212 if (cond->requires & ACL_USE_RTR_ANY) {
2213 struct acl *acl;
2214 const char *name;
2215
2216 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2217 name = acl ? acl->name : "(unknown)";
2218 Warning("parsing [%s:%d] : '%s' : acl '%s' involves some response-only criteria which will be ignored.\n",
2219 file, linenum, args[0], name);
2220 err_code |= ERR_WARN;
2221 }
2222 }
2223 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2224 rule->cond = cond;
2225 rule->expr = expr;
2226 rule->flags = flags;
2227 rule->table.name = name ? strdup(name) : NULL;
2228 LIST_INIT(&rule->list);
2229 if (flags & STK_ON_RSP)
2230 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2231 else
2232 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2233 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002235 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002236 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2239 curproxy->uri_auth = NULL; /* we must detach from the default config */
2240
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002241 if (!*args[1]) {
2242 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 } else if (!strcmp(args[1], "uri")) {
2244 if (*(args[2]) == 0) {
2245 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_ABORT;
2251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 }
2253 } else if (!strcmp(args[1], "realm")) {
2254 if (*(args[2]) == 0) {
2255 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2259 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_ABORT;
2261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002263 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002264 unsigned interval;
2265
2266 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2267 if (err) {
2268 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2269 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002272 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2273 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_ALERT | ERR_ABORT;
2275 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 } else if (!strcmp(args[1], "auth")) {
2278 if (*(args[2]) == 0) {
2279 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2283 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_ALERT | ERR_ABORT;
2285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 }
2287 } else if (!strcmp(args[1], "scope")) {
2288 if (*(args[2]) == 0) {
2289 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_ALERT | ERR_ABORT;
2295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 }
2297 } else if (!strcmp(args[1], "enable")) {
2298 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2299 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_ABORT;
2301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002303 } else if (!strcmp(args[1], "hide-version")) {
2304 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2305 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002306 err_code |= ERR_ALERT | ERR_ABORT;
2307 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002308 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002309 } else if (!strcmp(args[1], "show-legends")) {
2310 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2311 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2312 err_code |= ERR_ALERT | ERR_ABORT;
2313 goto out;
2314 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002315 } else if (!strcmp(args[1], "show-node")) {
2316
2317 if (*args[2]) {
2318 int i;
2319 char c;
2320
2321 for (i=0; args[2][i]; i++) {
2322 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002323 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002324 break;
2325 }
2326
2327 if (!i || args[2][i]) {
2328 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2329 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2330 file, linenum, args[0], args[1]);
2331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
2333 }
2334 }
2335
2336 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2337 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2338 err_code |= ERR_ALERT | ERR_ABORT;
2339 goto out;
2340 }
2341 } else if (!strcmp(args[1], "show-desc")) {
2342 char *desc = NULL;
2343
2344 if (*args[2]) {
2345 int i, len=0;
2346 char *d;
2347
2348 for(i=2; *args[i]; i++)
2349 len += strlen(args[i])+1;
2350
2351 desc = d = (char *)calloc(1, len);
2352
2353 d += sprintf(d, "%s", args[2]);
2354 for(i=3; *args[i]; i++)
2355 d += sprintf(d, " %s", args[i]);
2356 }
2357
2358 if (!*args[2] && !global.desc)
2359 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2360 file, linenum, args[1]);
2361 else {
2362 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2363 free(desc);
2364 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2365 err_code |= ERR_ALERT | ERR_ABORT;
2366 goto out;
2367 }
2368 free(desc);
2369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002371stats_error_parsing:
2372 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2373 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }
2377 }
2378 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002379 int optnum;
2380
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002381 if (*(args[1]) == '\0') {
2382 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2383 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002387
2388 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2389 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002390 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2391 err_code |= ERR_WARN;
2392 goto out;
2393 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002394
Willy Tarreau3842f002009-06-14 11:39:52 +02002395 curproxy->no_options &= ~cfg_opts[optnum].val;
2396 curproxy->options &= ~cfg_opts[optnum].val;
2397
2398 switch (kwm) {
2399 case KWM_STD:
2400 curproxy->options |= cfg_opts[optnum].val;
2401 break;
2402 case KWM_NO:
2403 curproxy->no_options |= cfg_opts[optnum].val;
2404 break;
2405 case KWM_DEF: /* already cleared */
2406 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002407 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002408
Willy Tarreau93893792009-07-23 13:19:11 +02002409 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002410 }
2411 }
2412
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002413 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2414 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002415 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2416 err_code |= ERR_WARN;
2417 goto out;
2418 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002419
Willy Tarreau3842f002009-06-14 11:39:52 +02002420 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2421 curproxy->options2 &= ~cfg_opts2[optnum].val;
2422
2423 switch (kwm) {
2424 case KWM_STD:
2425 curproxy->options2 |= cfg_opts2[optnum].val;
2426 break;
2427 case KWM_NO:
2428 curproxy->no_options2 |= cfg_opts2[optnum].val;
2429 break;
2430 case KWM_DEF: /* already cleared */
2431 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002432 }
Willy Tarreau93893792009-07-23 13:19:11 +02002433 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002434 }
2435 }
2436
Willy Tarreau3842f002009-06-14 11:39:52 +02002437 if (kwm != KWM_STD) {
2438 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002439 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002442 }
2443
Emeric Brun3a058f32009-06-30 18:26:00 +02002444 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002446 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002448 if (*(args[2]) != '\0') {
2449 if (!strcmp(args[2], "clf")) {
2450 curproxy->options2 |= PR_O2_CLFLOG;
2451 } else {
2452 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002455 }
2456 }
2457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 else if (!strcmp(args[1], "tcplog"))
2459 /* generate a detailed TCP log */
2460 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 else if (!strcmp(args[1], "tcpka")) {
2462 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002463 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002465
2466 if (curproxy->cap & PR_CAP_FE)
2467 curproxy->options |= PR_O_TCP_CLI_KA;
2468 if (curproxy->cap & PR_CAP_BE)
2469 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 }
2471 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002472 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_WARN;
2474
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002476 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002477 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002478 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002479 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002480 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 if (!*args[2]) { /* no argument */
2482 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2483 curproxy->check_len = strlen(DEF_CHECK_REQ);
2484 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002485 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 curproxy->check_req = (char *)malloc(reqlen);
2487 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2488 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2489 } else { /* more arguments : METHOD URI [HTTP_VER] */
2490 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2491 if (*args[4])
2492 reqlen += strlen(args[4]);
2493 else
2494 reqlen += strlen("HTTP/1.0");
2495
2496 curproxy->check_req = (char *)malloc(reqlen);
2497 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2498 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2499 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002500 }
2501 else if (!strcmp(args[1], "ssl-hello-chk")) {
2502 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002503 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002505
Willy Tarreaua534fea2008-08-03 12:19:50 +02002506 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002507 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002508 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002509 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002510 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 }
Willy Tarreau23677902007-05-08 23:50:35 +02002512 else if (!strcmp(args[1], "smtpchk")) {
2513 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002514 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002515 curproxy->options &= ~PR_O_HTTP_CHK;
2516 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002517 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002518 curproxy->options |= PR_O_SMTP_CHK;
2519
2520 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2521 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2522 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2523 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2524 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2525 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2526 curproxy->check_req = (char *)malloc(reqlen);
2527 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2528 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2529 } else {
2530 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2531 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2532 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2533 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2534 }
2535 }
2536 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002537 else if (!strcmp(args[1], "mysql-check")) {
2538 /* use MYSQL request to check servers' health */
2539 free(curproxy->check_req);
2540 curproxy->options &= ~PR_O_HTTP_CHK;
2541 curproxy->options &= ~PR_O_SSL3_CHK;
2542 curproxy->options &= ~PR_O_SMTP_CHK;
2543 curproxy->options2 |= PR_O2_MYSQL_CHK;
2544 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002545 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002546 int cur_arg;
2547
2548 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2549 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002550 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002551
2552 curproxy->options |= PR_O_FWDFOR;
2553
2554 free(curproxy->fwdfor_hdr_name);
2555 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2556 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2557
2558 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2559 cur_arg = 2;
2560 while (*(args[cur_arg])) {
2561 if (!strcmp(args[cur_arg], "except")) {
2562 /* suboption except - needs additional argument for it */
2563 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2564 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2565 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002568 }
2569 /* flush useless bits */
2570 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002571 cur_arg += 2;
2572 } else if (!strcmp(args[cur_arg], "header")) {
2573 /* suboption header - needs additional argument for it */
2574 if (*(args[cur_arg+1]) == 0) {
2575 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2576 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002579 }
2580 free(curproxy->fwdfor_hdr_name);
2581 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2582 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2583 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002584 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002585 /* unknown suboption - catchall */
2586 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2587 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002590 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002591 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002592 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002593 else if (!strcmp(args[1], "originalto")) {
2594 int cur_arg;
2595
2596 /* insert x-original-to field, but not for the IP address listed as an except.
2597 * set default options (ie: bitfield, header name, etc)
2598 */
2599
2600 curproxy->options |= PR_O_ORGTO;
2601
2602 free(curproxy->orgto_hdr_name);
2603 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2604 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2605
2606 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2607 cur_arg = 2;
2608 while (*(args[cur_arg])) {
2609 if (!strcmp(args[cur_arg], "except")) {
2610 /* suboption except - needs additional argument for it */
2611 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2612 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2613 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002616 }
2617 /* flush useless bits */
2618 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2619 cur_arg += 2;
2620 } else if (!strcmp(args[cur_arg], "header")) {
2621 /* suboption header - needs additional argument for it */
2622 if (*(args[cur_arg+1]) == 0) {
2623 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2624 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002627 }
2628 free(curproxy->orgto_hdr_name);
2629 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2630 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2631 cur_arg += 2;
2632 } else {
2633 /* unknown suboption - catchall */
2634 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2635 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002638 }
2639 } /* end while loop */
2640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 else {
2642 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }
Willy Tarreau93893792009-07-23 13:19:11 +02002646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002648 else if (!strcmp(args[0], "default_backend")) {
2649 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002651
2652 if (*(args[1]) == 0) {
2653 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002656 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002657 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002658 curproxy->defbe.name = strdup(args[1]);
2659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002661 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002663
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002664 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 /* enable reconnections to dispatch */
2668 curproxy->options |= PR_O_REDISP;
2669 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002670 else if (!strcmp(args[0], "http-check")) {
2671 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002672 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002673
2674 if (strcmp(args[1], "disable-on-404") == 0) {
2675 /* enable a graceful server shutdown on an HTTP 404 response */
2676 curproxy->options |= PR_O_DISABLE404;
2677 }
2678 else {
2679 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002682 }
2683 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002684 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002685 if (curproxy == &defproxy) {
2686 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002687 err_code |= ERR_ALERT | ERR_FATAL;
2688 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002689 }
2690
Willy Tarreaub80c2302007-11-30 20:51:32 +01002691 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002693
2694 if (strcmp(args[1], "fail") == 0) {
2695 /* add a condition to fail monitor requests */
2696 int pol = ACL_COND_NONE;
2697 struct acl_cond *cond;
2698
2699 if (!strcmp(args[2], "if"))
2700 pol = ACL_COND_IF;
2701 else if (!strcmp(args[2], "unless"))
2702 pol = ACL_COND_UNLESS;
2703
2704 if (pol == ACL_COND_NONE) {
2705 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2706 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002709 }
2710
2711 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2712 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2713 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002716 }
Willy Tarreau88922352009-10-04 22:02:50 +02002717 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002718 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002719 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002720 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2721 }
2722 else {
2723 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002726 }
2727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728#ifdef TPROXY
2729 else if (!strcmp(args[0], "transparent")) {
2730 /* enable transparent proxy connections */
2731 curproxy->options |= PR_O_TRANSP;
2732 }
2733#endif
2734 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002735 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002737
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 if (*(args[1]) == 0) {
2739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 }
2743 curproxy->maxconn = atol(args[1]);
2744 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002745 else if (!strcmp(args[0], "backlog")) { /* backlog */
2746 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002747 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002748
2749 if (*(args[1]) == 0) {
2750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002753 }
2754 curproxy->backlog = atol(args[1]);
2755 }
Willy Tarreau86034312006-12-29 00:10:33 +01002756 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002759
Willy Tarreau86034312006-12-29 00:10:33 +01002760 if (*(args[1]) == 0) {
2761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002764 }
2765 curproxy->fullconn = atol(args[1]);
2766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2768 if (*(args[1]) == 0) {
2769 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002773 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2774 if (err) {
2775 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2776 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002779 }
2780 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
2782 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2783 if (curproxy == &defproxy) {
2784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002788 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002790
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 if (strchr(args[1], ':') == NULL) {
2792 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 }
2796 curproxy->dispatch_addr = *str2sa(args[1]);
2797 }
2798 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002799 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002801
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002802 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002803 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2804 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002809 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2810 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2811 err_code |= ERR_WARN;
2812
2813 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2814 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2815 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2816 }
2817 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2818 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2819 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2820 }
2821 else {
2822 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
2825 }
2826 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002827 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002829 char *rport, *raddr;
2830 short realport = 0;
2831 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002833 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002838 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840
2841 if (!*args[2]) {
2842 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2843 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002847
2848 err = invalid_char(args[1]);
2849 if (err) {
2850 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2851 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002854 }
2855
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2857 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_ALERT | ERR_ABORT;
2859 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 }
2861
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002862 if (!defsrv) {
2863 /* the servers are linked backwards first */
2864 newsrv->next = curproxy->srv;
2865 curproxy->srv = newsrv;
2866 newsrv->proxy = curproxy;
2867 newsrv->conf.file = file;
2868 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002870 LIST_INIT(&newsrv->pendconns);
2871 do_check = 0;
2872 newsrv->state = SRV_RUNNING; /* early server setup */
2873 newsrv->last_change = now.tv_sec;
2874 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002876 /* several ways to check the port component :
2877 * - IP => port=+0, relative
2878 * - IP: => port=+0, relative
2879 * - IP:N => port=N, absolute
2880 * - IP:+N => port=+N, relative
2881 * - IP:-N => port=-N, relative
2882 */
2883 raddr = strdup(args[2]);
2884 rport = strchr(raddr, ':');
2885 if (rport) {
2886 *rport++ = 0;
2887 realport = atol(rport);
2888 if (!isdigit((unsigned char)*rport))
2889 newsrv->state |= SRV_MAPPORTS;
2890 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002892
2893 newsrv->addr = *str2sa(raddr);
2894 newsrv->addr.sin_port = htons(realport);
2895 free(raddr);
2896
2897 newsrv->check_port = curproxy->defsrv.check_port;
2898 newsrv->inter = curproxy->defsrv.inter;
2899 newsrv->fastinter = curproxy->defsrv.fastinter;
2900 newsrv->downinter = curproxy->defsrv.downinter;
2901 newsrv->rise = curproxy->defsrv.rise;
2902 newsrv->fall = curproxy->defsrv.fall;
2903 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2904 newsrv->minconn = curproxy->defsrv.minconn;
2905 newsrv->maxconn = curproxy->defsrv.maxconn;
2906 newsrv->slowstart = curproxy->defsrv.slowstart;
2907 newsrv->onerror = curproxy->defsrv.onerror;
2908 newsrv->consecutive_errors_limit
2909 = curproxy->defsrv.consecutive_errors_limit;
2910 newsrv->uweight = newsrv->iweight
2911 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002913 newsrv->curfd = -1; /* no health-check in progress */
2914 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002916 cur_arg = 3;
2917 } else {
2918 newsrv = &curproxy->defsrv;
2919 cur_arg = 1;
2920 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002921
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002923 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002924 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002925
2926 if (!*args[cur_arg + 1]) {
2927 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2928 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002931 }
2932
2933 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002934 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002935
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002936 if (newsrv->puid <= 0) {
2937 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002938 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002941 }
2942
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002943 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2944 if (node) {
2945 struct server *target = container_of(node, struct server, conf.id);
2946 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2947 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002952 cur_arg += 2;
2953 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002954 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 newsrv->cookie = strdup(args[cur_arg + 1]);
2956 newsrv->cklen = strlen(args[cur_arg + 1]);
2957 cur_arg += 2;
2958 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002959 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01002960 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2961 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2962 cur_arg += 2;
2963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002965 if (!*args[cur_arg + 1]) {
2966 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2967 file, linenum, args[cur_arg]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002973 if (newsrv->rise <= 0) {
2974 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2975 file, linenum, args[cur_arg]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 newsrv->health = newsrv->rise;
2981 cur_arg += 2;
2982 }
2983 else if (!strcmp(args[cur_arg], "fall")) {
2984 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002985
2986 if (!*args[cur_arg + 1]) {
2987 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2988 file, linenum, args[cur_arg]);
2989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
2991 }
2992
2993 if (newsrv->fall <= 0) {
2994 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2995 file, linenum, args[cur_arg]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 cur_arg += 2;
3001 }
3002 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003003 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3004 if (err) {
3005 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3006 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003009 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003010 if (val <= 0) {
3011 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3012 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003015 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003016 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 cur_arg += 2;
3018 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003019 else if (!strcmp(args[cur_arg], "fastinter")) {
3020 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3021 if (err) {
3022 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3023 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003026 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003027 if (val <= 0) {
3028 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3029 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003032 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003033 newsrv->fastinter = val;
3034 cur_arg += 2;
3035 }
3036 else if (!strcmp(args[cur_arg], "downinter")) {
3037 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3038 if (err) {
3039 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3040 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003043 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003044 if (val <= 0) {
3045 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3046 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003049 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003050 newsrv->downinter = val;
3051 cur_arg += 2;
3052 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003053 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003054 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003055 cur_arg += 2;
3056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 else if (!strcmp(args[cur_arg], "port")) {
3058 newsrv->check_port = atol(args[cur_arg + 1]);
3059 cur_arg += 2;
3060 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003061 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 newsrv->state |= SRV_BACKUP;
3063 cur_arg ++;
3064 }
3065 else if (!strcmp(args[cur_arg], "weight")) {
3066 int w;
3067 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003068 if (w < 0 || w > 256) {
3069 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003074 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 cur_arg += 2;
3076 }
3077 else if (!strcmp(args[cur_arg], "minconn")) {
3078 newsrv->minconn = atol(args[cur_arg + 1]);
3079 cur_arg += 2;
3080 }
3081 else if (!strcmp(args[cur_arg], "maxconn")) {
3082 newsrv->maxconn = atol(args[cur_arg + 1]);
3083 cur_arg += 2;
3084 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003085 else if (!strcmp(args[cur_arg], "maxqueue")) {
3086 newsrv->maxqueue = atol(args[cur_arg + 1]);
3087 cur_arg += 2;
3088 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003089 else if (!strcmp(args[cur_arg], "slowstart")) {
3090 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003091 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003092 if (err) {
3093 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3094 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003097 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003098 if (val <= 0) {
3099 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3100 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003103 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003104 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003105 cur_arg += 2;
3106 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003107 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003108
3109 if (!*args[cur_arg + 1]) {
3110 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3111 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003114 }
3115
3116 newsrv->trackit = strdup(args[cur_arg + 1]);
3117
3118 cur_arg += 2;
3119 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003120 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 global.maxsock++;
3122 do_check = 1;
3123 cur_arg += 1;
3124 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003125 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003126 if (!strcmp(args[cur_arg + 1], "none"))
3127 newsrv->observe = HANA_OBS_NONE;
3128 else if (!strcmp(args[cur_arg + 1], "layer4"))
3129 newsrv->observe = HANA_OBS_LAYER4;
3130 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3131 if (curproxy->mode != PR_MODE_HTTP) {
3132 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3133 file, linenum, args[cur_arg + 1]);
3134 err_code |= ERR_ALERT;
3135 }
3136 newsrv->observe = HANA_OBS_LAYER7;
3137 }
3138 else {
3139 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3140 "'l4events', 'http-responses' but get '%s'\n",
3141 file, linenum, args[cur_arg], args[cur_arg + 1]);
3142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
3146 cur_arg += 2;
3147 }
3148 else if (!strcmp(args[cur_arg], "on-error")) {
3149 if (!strcmp(args[cur_arg + 1], "fastinter"))
3150 newsrv->onerror = HANA_ONERR_FASTINTER;
3151 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3152 newsrv->onerror = HANA_ONERR_FAILCHK;
3153 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3154 newsrv->onerror = HANA_ONERR_SUDDTH;
3155 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3156 newsrv->onerror = HANA_ONERR_MARKDWN;
3157 else {
3158 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3159 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3160 file, linenum, args[cur_arg], args[cur_arg + 1]);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164
3165 cur_arg += 2;
3166 }
3167 else if (!strcmp(args[cur_arg], "error-limit")) {
3168 if (!*args[cur_arg + 1]) {
3169 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3170 file, linenum, args[cur_arg]);
3171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
3173 }
3174
3175 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3176
3177 if (newsrv->consecutive_errors_limit <= 0) {
3178 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3179 file, linenum, args[cur_arg]);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003184 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003185 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003187#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003188 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003189 file, linenum, "source", "usesrc");
3190#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003191 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003193#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003198 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3199
3200 if (port_low != port_high) {
3201 int i;
3202 if (port_low <= 0 || port_low > 65535 ||
3203 port_high <= 0 || port_high > 65535 ||
3204 port_low > port_high) {
3205 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3206 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003209 }
3210 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3211 for (i = 0; i < newsrv->sport_range->size; i++)
3212 newsrv->sport_range->ports[i] = port_low + i;
3213 }
3214
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003216 while (*(args[cur_arg])) {
3217 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003218#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3219#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003220 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3221 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3222 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003225 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003226#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003227 if (!*args[cur_arg + 1]) {
3228 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3229 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003232 }
3233 if (!strcmp(args[cur_arg + 1], "client")) {
3234 newsrv->state |= SRV_TPROXY_CLI;
3235 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3236 newsrv->state |= SRV_TPROXY_CIP;
3237 } else {
3238 newsrv->state |= SRV_TPROXY_ADDR;
3239 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3240 }
3241 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003242#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003243 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003244#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003245 cur_arg += 2;
3246 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003247#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003248 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003249 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003252#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3253 } /* "usesrc" */
3254
3255 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3256#ifdef SO_BINDTODEVICE
3257 if (!*args[cur_arg + 1]) {
3258 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3259 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003262 }
3263 if (newsrv->iface_name)
3264 free(newsrv->iface_name);
3265
3266 newsrv->iface_name = strdup(args[cur_arg + 1]);
3267 newsrv->iface_len = strlen(newsrv->iface_name);
3268 global.last_checks |= LSTCHK_NETADM;
3269#else
3270 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3271 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003274#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003275 cur_arg += 2;
3276 continue;
3277 }
3278 /* this keyword in not an option of "source" */
3279 break;
3280 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003282 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003283 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3284 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003289 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003290 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 +01003291 file, linenum, newsrv->id);
3292 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003293 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 +01003294 file, linenum);
3295
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
3299 }
3300
3301 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003302 if (newsrv->trackit) {
3303 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3304 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003307 }
3308
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003309 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3310 newsrv->check_port = newsrv->check_addr.sin_port;
3311
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3313 newsrv->check_port = realport; /* by default */
3314 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003315 /* not yet valid, because no port was set on
3316 * the server either. We'll check if we have
3317 * a known port on the first listener.
3318 */
3319 struct listener *l;
3320 l = curproxy->listen;
3321 if (l) {
3322 int port;
3323 port = (l->addr.ss_family == AF_INET6)
3324 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3325 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3326 newsrv->check_port = port;
3327 }
3328 }
3329 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3331 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003335
3336 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 newsrv->state |= SRV_CHECKED;
3338 }
3339
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003340 if (!defsrv) {
3341 if (newsrv->state & SRV_BACKUP)
3342 curproxy->srv_bck++;
3343 else
3344 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003345
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003346 newsrv->prev_state = newsrv->state;
3347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
3349 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003350 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 int facility;
3352
3353 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3354 curproxy->logfac1 = global.logfac1;
3355 curproxy->logsrv1 = global.logsrv1;
3356 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003357 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 curproxy->logfac2 = global.logfac2;
3359 curproxy->logsrv2 = global.logsrv2;
3360 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003361 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
3363 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003364 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365
3366 facility = get_log_facility(args[2]);
3367 if (facility < 0) {
3368 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3369 exit(1);
3370 }
3371
3372 level = 7; /* max syslog level = debug */
3373 if (*(args[3])) {
3374 level = get_log_level(args[3]);
3375 if (level < 0) {
3376 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3377 exit(1);
3378 }
3379 }
3380
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003381 minlvl = 0; /* limit syslog level to this level (emerg) */
3382 if (*(args[4])) {
3383 minlvl = get_log_level(args[4]);
3384 if (level < 0) {
3385 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3386 exit(1);
3387 }
3388 }
3389
Robert Tsai81ae1952007-12-05 10:47:29 +01003390 if (args[1][0] == '/') {
3391 logsrv.u.addr.sa_family = AF_UNIX;
3392 logsrv.u.un = *str2sun(args[1]);
3393 } else {
3394 logsrv.u.addr.sa_family = AF_INET;
3395 logsrv.u.in = *str2sa(args[1]);
3396 if (!logsrv.u.in.sin_port) {
3397 logsrv.u.in.sin_port =
3398 htons(SYSLOG_PORT);
3399 }
3400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401
3402 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003403 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 curproxy->logfac1 = facility;
3405 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003406 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 }
3408 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003409 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 curproxy->logfac2 = facility;
3411 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003412 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 }
3414 else {
3415 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
3419 }
3420 else {
3421 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3422 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 }
3426 }
3427 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003428 int cur_arg;
3429
Willy Tarreau977b8e42006-12-29 14:19:17 +01003430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003432
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003434 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3435 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003439
3440 /* we must first clear any optional default setting */
3441 curproxy->options &= ~PR_O_TPXY_MASK;
3442 free(curproxy->iface_name);
3443 curproxy->iface_name = NULL;
3444 curproxy->iface_len = 0;
3445
Willy Tarreaubaaee002006-06-26 02:48:02 +02003446 curproxy->source_addr = *str2sa(args[1]);
3447 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003448
3449 cur_arg = 2;
3450 while (*(args[cur_arg])) {
3451 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003452#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3453#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003454 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3455 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3456 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003457 err_code |= ERR_ALERT | ERR_FATAL;
3458 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003459 }
3460#endif
3461 if (!*args[cur_arg + 1]) {
3462 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3463 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003466 }
3467
3468 if (!strcmp(args[cur_arg + 1], "client")) {
3469 curproxy->options |= PR_O_TPXY_CLI;
3470 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3471 curproxy->options |= PR_O_TPXY_CIP;
3472 } else {
3473 curproxy->options |= PR_O_TPXY_ADDR;
3474 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3475 }
3476 global.last_checks |= LSTCHK_NETADM;
3477#if !defined(CONFIG_HAP_LINUX_TPROXY)
3478 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003479#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003480#else /* no TPROXY support */
3481 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003482 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003485#endif
3486 cur_arg += 2;
3487 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003488 }
3489
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003490 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3491#ifdef SO_BINDTODEVICE
3492 if (!*args[cur_arg + 1]) {
3493 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3494 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003497 }
3498 if (curproxy->iface_name)
3499 free(curproxy->iface_name);
3500
3501 curproxy->iface_name = strdup(args[cur_arg + 1]);
3502 curproxy->iface_len = strlen(curproxy->iface_name);
3503 global.last_checks |= LSTCHK_NETADM;
3504#else
3505 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3506 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003509#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003510 cur_arg += 2;
3511 continue;
3512 }
3513 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3514 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003519 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3520 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3521 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3526 regex_t *preg;
3527 if (curproxy == &defproxy) {
3528 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003532 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003533 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003534
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 if (*(args[1]) == 0 || *(args[2]) == 0) {
3536 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3537 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 }
3541
3542 preg = calloc(1, sizeof(regex_t));
3543 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3544 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 }
3548
3549 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3550 if (err) {
3551 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3552 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
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], "reqdel")) { /* delete request header from a regex */
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_REMOVE, 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], "reqdeny")) { /* deny 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_DENY, 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 }
3609 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
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 Tarreaubaaee002006-06-26 02:48:02 +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 Tarreaubaaee002006-06-26 02:48:02 +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 Tarreaubaaee002006-06-26 02:48:02 +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 Tarreaubaaee002006-06-26 02:48:02 +02003630 }
3631
3632 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003633 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 }
3635 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3636 regex_t *preg;
3637 if (curproxy == &defproxy) {
3638 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 Tarreaubaaee002006-06-26 02:48:02 +02003641 }
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 Tarreau977b8e42006-12-29 14:19:17 +01003644
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 if (*(args[1]) == 0) {
3646 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650
3651 preg = calloc(1, sizeof(regex_t));
3652 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3653 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
3657
3658 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003659 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003661 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3662 regex_t *preg;
3663 if (curproxy == &defproxy) {
3664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003667 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003668 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003670
Willy Tarreaub8750a82006-09-03 09:56:00 +02003671 if (*(args[1]) == 0) {
3672 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003675 }
3676
3677 preg = calloc(1, sizeof(regex_t));
3678 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3679 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003682 }
3683
3684 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003685 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003686 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003687 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3688 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003689 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003690 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003693 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003694 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003696
Willy Tarreau977b8e42006-12-29 14:19:17 +01003697 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003698 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003702 }
3703
3704 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003705 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003706 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003709 }
3710
3711 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003712 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003713 }
3714 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3715 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003716 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003720 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003721 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003723
Willy Tarreau977b8e42006-12-29 14:19:17 +01003724 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003725 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003729 }
3730
3731 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003732 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003733 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003736 }
3737
3738 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003739 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3742 regex_t *preg;
3743 if (curproxy == &defproxy) {
3744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003748 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003750
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 if (*(args[1]) == 0 || *(args[2]) == 0) {
3752 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3753 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 }
3757
3758 preg = calloc(1, sizeof(regex_t));
3759 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3760 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763 }
3764
3765 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3766 if (err) {
3767 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3768 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 }
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], "reqidel")) { /* delete request header from a regex ignoring case */
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_REMOVE, 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], "reqideny")) { /* deny 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_DENY, 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 }
3826 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
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 Tarreaubaaee002006-06-26 02:48:02 +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 Tarreaubaaee002006-06-26 02:48:02 +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 Tarreaubaaee002006-06-26 02:48:02 +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 Tarreaubaaee002006-06-26 02:48:02 +02003847 }
3848
3849 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003850 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
3852 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3853 regex_t *preg;
3854 if (curproxy == &defproxy) {
3855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003859 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003861
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 if (*(args[1]) == 0) {
3863 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
3867
3868 preg = calloc(1, sizeof(regex_t));
3869 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3870 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
3874
3875 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003876 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003878 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3879 regex_t *preg;
3880 if (curproxy == &defproxy) {
3881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003885 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003887
Willy Tarreaub8750a82006-09-03 09:56:00 +02003888 if (*(args[1]) == 0) {
3889 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003892 }
3893
3894 preg = calloc(1, sizeof(regex_t));
3895 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3896 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003899 }
3900
3901 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003902 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003905 struct wordlist *wl;
3906
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 if (curproxy == &defproxy) {
3908 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003912 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 if (*(args[1]) == 0) {
3916 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003920
3921 wl = calloc(1, sizeof(*wl));
3922 wl->s = strdup(args[1]);
3923 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003924 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 }
3926 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3927 regex_t *preg;
3928
3929 if (*(args[1]) == 0 || *(args[2]) == 0) {
3930 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003935 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003937
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 preg = calloc(1, sizeof(regex_t));
3939 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3940 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 }
3944
3945 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3946 if (err) {
3947 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3948 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003952 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 }
3954 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3955 regex_t *preg;
3956 if (curproxy == &defproxy) {
3957 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003961 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003962 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003963
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 if (*(args[1]) == 0) {
3965 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
3969
3970 preg = calloc(1, sizeof(regex_t));
3971 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3972 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 }
3976
3977 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3978 if (err) {
3979 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3980 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 }
3984 }
3985 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3986 regex_t *preg;
3987 if (curproxy == &defproxy) {
3988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003992 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003994
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 if (*(args[1]) == 0) {
3996 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 }
4000
4001 preg = calloc(1, sizeof(regex_t));
4002 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4003 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 }
4007
4008 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4009 if (err) {
4010 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4011 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 }
4015 }
4016 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
4017 regex_t *preg;
4018 if (curproxy == &defproxy) {
4019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004023 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025
4026 if (*(args[1]) == 0 || *(args[2]) == 0) {
4027 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4028 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 }
4032
4033 preg = calloc(1, sizeof(regex_t));
4034 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4035 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 }
4039
4040 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
4041 if (err) {
4042 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4043 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 }
4047 }
4048 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
4049 regex_t *preg;
4050 if (curproxy == &defproxy) {
4051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004055 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004057
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 if (*(args[1]) == 0) {
4059 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 }
4063
4064 preg = calloc(1, sizeof(regex_t));
4065 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4066 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 }
4070
4071 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4072 if (err) {
4073 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4074 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077 }
4078 }
4079 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
4080 regex_t *preg;
4081 if (curproxy == &defproxy) {
4082 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004085 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004086 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004087 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004088
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089 if (*(args[1]) == 0) {
4090 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093 }
4094
4095 preg = calloc(1, sizeof(regex_t));
4096 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4097 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 }
4101
4102 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4103 if (err) {
4104 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4105 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 }
4109 }
4110 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004111 struct wordlist *wl;
4112
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 if (curproxy == &defproxy) {
4114 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004118 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004119 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 if (*(args[1]) == 0) {
4122 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 }
4126
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004127 wl = calloc(1, sizeof(*wl));
4128 wl->s = strdup(args[1]);
4129 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 }
4131 else if (!strcmp(args[0], "errorloc") ||
4132 !strcmp(args[0], "errorloc302") ||
4133 !strcmp(args[0], "errorloc303")) { /* error location */
4134 int errnum, errlen;
4135 char *err;
4136
Willy Tarreau977b8e42006-12-29 14:19:17 +01004137 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004138 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004139
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004141 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 }
4145
4146 errnum = atol(args[1]);
4147 if (!strcmp(args[0], "errorloc303")) {
4148 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4149 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4150 } else {
4151 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4152 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4153 }
4154
Willy Tarreau0f772532006-12-23 20:51:41 +01004155 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4156 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004157 chunk_destroy(&curproxy->errmsg[rc]);
4158 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004159 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004162
4163 if (rc >= HTTP_ERR_SIZE) {
4164 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4165 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 free(err);
4167 }
4168 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004169 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4170 int errnum, errlen, fd;
4171 char *err;
4172 struct stat stat;
4173
4174 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004176
4177 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004178 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004181 }
4182
4183 fd = open(args[2], O_RDONLY);
4184 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4185 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4186 file, linenum, args[2], args[1]);
4187 if (fd >= 0)
4188 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004191 }
4192
Willy Tarreau27a674e2009-08-17 07:23:33 +02004193 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004194 errlen = stat.st_size;
4195 } else {
4196 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004197 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004198 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004199 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004200 }
4201
4202 err = malloc(errlen); /* malloc() must succeed during parsing */
4203 errnum = read(fd, err, errlen);
4204 if (errnum != errlen) {
4205 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4206 file, linenum, args[2], args[1]);
4207 close(fd);
4208 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004211 }
4212 close(fd);
4213
4214 errnum = atol(args[1]);
4215 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4216 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004217 chunk_destroy(&curproxy->errmsg[rc]);
4218 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004219 break;
4220 }
4221 }
4222
4223 if (rc >= HTTP_ERR_SIZE) {
4224 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4225 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004226 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004227 free(err);
4228 }
4229 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004231 struct cfg_kw_list *kwl;
4232 int index;
4233
4234 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4235 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4236 if (kwl->kw[index].section != CFG_LISTEN)
4237 continue;
4238 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4239 /* prepare error message just in case */
4240 snprintf(trash, sizeof(trash),
4241 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004242 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4243 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004244 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004247 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004248 else if (rc > 0) {
4249 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004250 err_code |= ERR_WARN;
4251 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004252 }
Willy Tarreau93893792009-07-23 13:19:11 +02004253 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004254 }
4255 }
4256 }
4257
Willy Tarreau6daf3432008-01-22 16:44:08 +01004258 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 }
Willy Tarreau93893792009-07-23 13:19:11 +02004262 out:
4263 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004264}
4265
4266
4267/*
4268 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004269 * Returns the error code, 0 if OK, or any combination of :
4270 * - ERR_ABORT: must abort ASAP
4271 * - ERR_FATAL: we can continue parsing but not start the service
4272 * - ERR_WARN: a warning has been emitted
4273 * - ERR_ALERT: an alert has been emitted
4274 * Only the two first ones can stop processing, the two others are just
4275 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004277int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004279 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 FILE *f;
4281 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004283 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 if ((f=fopen(file,"r")) == NULL)
4286 return -1;
4287
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004288 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004289 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004290 char *end;
4291 char *args[MAX_LINE_ARGS + 1];
4292 char *line = thisline;
4293
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 linenum++;
4295
4296 end = line + strlen(line);
4297
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004298 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4299 /* Check if we reached the limit and the last char is not \n.
4300 * Watch out for the last line without the terminating '\n'!
4301 */
4302 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004303 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004305 }
4306
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004308 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 line++;
4310
4311 arg = 0;
4312 args[arg] = line;
4313
4314 while (*line && arg < MAX_LINE_ARGS) {
4315 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4316 * C equivalent value. Other combinations left unchanged (eg: \1).
4317 */
4318 if (*line == '\\') {
4319 int skip = 0;
4320 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4321 *line = line[1];
4322 skip = 1;
4323 }
4324 else if (line[1] == 'r') {
4325 *line = '\r';
4326 skip = 1;
4327 }
4328 else if (line[1] == 'n') {
4329 *line = '\n';
4330 skip = 1;
4331 }
4332 else if (line[1] == 't') {
4333 *line = '\t';
4334 skip = 1;
4335 }
4336 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004337 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 unsigned char hex1, hex2;
4339 hex1 = toupper(line[2]) - '0';
4340 hex2 = toupper(line[3]) - '0';
4341 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4342 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4343 *line = (hex1<<4) + hex2;
4344 skip = 3;
4345 }
4346 else {
4347 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004348 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 }
4350 }
4351 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004352 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 end -= skip;
4354 }
4355 line++;
4356 }
4357 else if (*line == '#' || *line == '\n' || *line == '\r') {
4358 /* end of string, end of loop */
4359 *line = 0;
4360 break;
4361 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004362 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004364 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004365 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004366 line++;
4367 args[++arg] = line;
4368 }
4369 else {
4370 line++;
4371 }
4372 }
4373
4374 /* empty line */
4375 if (!**args)
4376 continue;
4377
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004378 if (*line) {
4379 /* we had to stop due to too many args.
4380 * Let's terminate the string, print the offending part then cut the
4381 * last arg.
4382 */
4383 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4384 line++;
4385 *line = '\0';
4386
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004387 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004388 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004389 err_code |= ERR_ALERT | ERR_FATAL;
4390 args[arg] = line;
4391 }
4392
Willy Tarreau540abe42007-05-02 20:50:16 +02004393 /* zero out remaining args and ensure that at least one entry
4394 * is zeroed out.
4395 */
4396 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 args[arg] = line;
4398 }
4399
Willy Tarreau3842f002009-06-14 11:39:52 +02004400 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004401 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004402 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004403 for (arg=0; *args[arg+1]; arg++)
4404 args[arg] = args[arg+1]; // shift args after inversion
4405 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004406 else if (!strcmp(args[0], "default")) {
4407 kwm = KWM_DEF;
4408 for (arg=0; *args[arg+1]; arg++)
4409 args[arg] = args[arg+1]; // shift args after inversion
4410 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004411
Willy Tarreau3842f002009-06-14 11:39:52 +02004412 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4413 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004415 }
4416
Willy Tarreau977b8e42006-12-29 14:19:17 +01004417 if (!strcmp(args[0], "listen") ||
4418 !strcmp(args[0], "frontend") ||
4419 !strcmp(args[0], "backend") ||
4420 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004421 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004423 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004424 cursection = strdup(args[0]);
4425 }
4426 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004428 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004429 cursection = strdup(args[0]);
4430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 /* else it's a section keyword */
4432
4433 switch (confsect) {
4434 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 break;
4437 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004438 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 break;
4440 default:
4441 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004444
4445 if (err_code & ERR_ABORT)
4446 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004448 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004449 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004451 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004452}
4453
Willy Tarreaubb925012009-07-23 13:36:36 +02004454/*
4455 * Returns the error code, 0 if OK, or any combination of :
4456 * - ERR_ABORT: must abort ASAP
4457 * - ERR_FATAL: we can continue parsing but not start the service
4458 * - ERR_WARN: a warning has been emitted
4459 * - ERR_ALERT: an alert has been emitted
4460 * Only the two first ones can stop processing, the two others are just
4461 * indicators.
4462 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004463int check_config_validity()
4464{
4465 int cfgerr = 0;
4466 struct proxy *curproxy = NULL;
4467 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004468 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004469 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470
4471 /*
4472 * Now, check for the integrity of all that we have collected.
4473 */
4474
4475 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004476 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004478 /* first, we will invert the proxy list order */
4479 curproxy = NULL;
4480 while (proxy) {
4481 struct proxy *next;
4482
4483 next = proxy->next;
4484 proxy->next = curproxy;
4485 curproxy = proxy;
4486 if (!next)
4487 break;
4488 proxy = next;
4489 }
4490
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004492 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 }
4496
4497 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004498 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004499 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004500 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004501 unsigned int next_id;
4502
4503 if (!curproxy->uuid) {
4504 /* proxy ID not set, use automatic numbering with first
4505 * spare entry starting with next_pxid.
4506 */
4507 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4508 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4509 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4510 next_pxid++;
4511 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004512
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004514 /* ensure we don't keep listeners uselessly bound */
4515 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 curproxy = curproxy->next;
4517 continue;
4518 }
4519
Willy Tarreauff01a212009-03-15 13:46:16 +01004520 switch (curproxy->mode) {
4521 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004522 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004523 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004524 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4525 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004526 cfgerr++;
4527 }
4528
4529 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004530 Warning("config : servers will be ignored for %s '%s'.\n",
4531 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004532 break;
4533
4534 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004535 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004536 break;
4537
4538 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004539 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004540 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004541 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4542 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004543 cfgerr++;
4544 }
4545 break;
4546 }
4547
4548 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004549 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4550 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 cfgerr++;
4552 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004553
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004554 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004555 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004556 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004557 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4558 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004559 cfgerr++;
4560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004562 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004563 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4564 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004565 cfgerr++;
4566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004568 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004569 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004571 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004572 }
4573 }
4574 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4575 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4576 /* If no LB algo is set in a backend, and we're not in
4577 * transparent mode, dispatch mode nor proxy mode, we
4578 * want to use balance roundrobin by default.
4579 */
4580 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4581 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004584
Willy Tarreau82936582007-11-30 15:20:09 +01004585 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4586 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004587 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4588 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004589 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004590 }
4591
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004592 /* if a default backend was specified, let's find it */
4593 if (curproxy->defbe.name) {
4594 struct proxy *target;
4595
Alex Williams96532db2009-11-01 21:27:13 -05004596 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004597 if (!target) {
4598 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4599 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004600 cfgerr++;
4601 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004602 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4603 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004604 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004605 } else {
4606 free(curproxy->defbe.name);
4607 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004608 /* we force the backend to be present on at least all of
4609 * the frontend's processes.
4610 */
4611 target->bind_proc = curproxy->bind_proc ?
4612 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 }
4614 }
4615
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004616 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004617 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4618 /* map jump target for ACT_SETBE in req_rep chain */
4619 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004620 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004621 struct proxy *target;
4622
Willy Tarreaua496b602006-12-17 23:15:24 +01004623 if (exp->action != ACT_SETBE)
4624 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004625
Alex Williams96532db2009-11-01 21:27:13 -05004626 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004627 if (!target) {
4628 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4629 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004630 cfgerr++;
4631 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004632 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4633 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004634 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004635 } else {
4636 free((void *)exp->replace);
4637 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004638 /* we force the backend to be present on at least all of
4639 * the frontend's processes.
4640 */
4641 target->bind_proc = curproxy->bind_proc ?
4642 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004643 }
4644 }
4645 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004646
4647 /* find the target proxy for 'use_backend' rules */
4648 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004649 struct proxy *target;
4650
Alex Williams96532db2009-11-01 21:27:13 -05004651 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004652
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004653 if (!target) {
4654 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4655 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004656 cfgerr++;
4657 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004658 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4659 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004660 cfgerr++;
4661 } else {
4662 free((void *)rule->be.name);
4663 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004664 /* we force the backend to be present on at least all of
4665 * the frontend's processes.
4666 */
4667 target->bind_proc = curproxy->bind_proc ?
4668 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004669 }
4670 }
4671
Emeric Brunb982a3d2010-01-04 15:45:53 +01004672 /* find the target table for 'stick' rules */
4673 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4674 struct proxy *target;
4675
Emeric Brun1d33b292010-01-04 15:47:17 +01004676 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4677 if (mrule->flags & STK_IS_STORE)
4678 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4679
Emeric Brunb982a3d2010-01-04 15:45:53 +01004680 if (mrule->table.name)
4681 target = findproxy(mrule->table.name, PR_CAP_BE);
4682 else
4683 target = curproxy;
4684
4685 if (!target) {
4686 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4687 curproxy->id, mrule->table.name);
4688 cfgerr++;
4689 }
4690 else if (target->table.size == 0) {
4691 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4692 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4693 cfgerr++;
4694 }
4695 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4696 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4697 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4698 cfgerr++;
4699 }
4700 else {
4701 free((void *)mrule->table.name);
4702 mrule->table.t = &(target->table);
4703 }
4704 }
4705
4706 /* find the target table for 'store response' rules */
4707 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4708 struct proxy *target;
4709
Emeric Brun1d33b292010-01-04 15:47:17 +01004710 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4711
Emeric Brunb982a3d2010-01-04 15:45:53 +01004712 if (mrule->table.name)
4713 target = findproxy(mrule->table.name, PR_CAP_BE);
4714 else
4715 target = curproxy;
4716
4717 if (!target) {
4718 Alert("Proxy '%s': unable to find store table '%s'.\n",
4719 curproxy->id, mrule->table.name);
4720 cfgerr++;
4721 }
4722 else if (target->table.size == 0) {
4723 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4724 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4725 cfgerr++;
4726 }
4727 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4728 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4729 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4730 cfgerr++;
4731 }
4732 else {
4733 free((void *)mrule->table.name);
4734 mrule->table.t = &(target->table);
4735 }
4736 }
4737
Willy Tarreau2738a142006-07-08 17:28:09 +02004738 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004739 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004740 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004741 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004742 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004743 " | While not properly invalid, you will certainly encounter various problems\n"
4744 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004745 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004746 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004747 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004748 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004749
Willy Tarreau1fa31262007-12-03 00:36:16 +01004750 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4751 * We must still support older configurations, so let's find out whether those
4752 * parameters have been set or must be copied from contimeouts.
4753 */
4754 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004755 if (!curproxy->timeout.tarpit ||
4756 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004757 /* tarpit timeout not set. We search in the following order:
4758 * default.tarpit, curr.connect, default.connect.
4759 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004760 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004761 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004762 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004763 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004764 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004765 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004766 }
4767 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004768 (!curproxy->timeout.queue ||
4769 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004770 /* queue timeout not set. We search in the following order:
4771 * default.queue, curr.connect, default.connect.
4772 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004773 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004774 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004775 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004776 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004777 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004778 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004779 }
4780 }
4781
Willy Tarreauf3c69202006-07-09 16:42:34 +02004782 if (curproxy->options & PR_O_SSL3_CHK) {
4783 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4784 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4785 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4786 }
4787
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004788 /* The small pools required for the capture lists */
4789 if (curproxy->nb_req_cap)
4790 curproxy->req_cap_pool = create_pool("ptrcap",
4791 curproxy->nb_req_cap * sizeof(char *),
4792 MEM_F_SHARED);
4793 if (curproxy->nb_rsp_cap)
4794 curproxy->rsp_cap_pool = create_pool("ptrcap",
4795 curproxy->nb_rsp_cap * sizeof(char *),
4796 MEM_F_SHARED);
4797
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004798 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4799 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4800 MEM_F_SHARED);
4801
Willy Tarreau86034312006-12-29 00:10:33 +01004802 /* for backwards compatibility with "listen" instances, if
4803 * fullconn is not set but maxconn is set, then maxconn
4804 * is used.
4805 */
4806 if (!curproxy->fullconn)
4807 curproxy->fullconn = curproxy->maxconn;
4808
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 /* first, we will invert the servers list order */
4810 newsrv = NULL;
4811 while (curproxy->srv) {
4812 struct server *next;
4813
4814 next = curproxy->srv->next;
4815 curproxy->srv->next = newsrv;
4816 newsrv = curproxy->srv;
4817 if (!next)
4818 break;
4819 curproxy->srv = next;
4820 }
4821
Willy Tarreau20697042007-11-15 23:26:18 +01004822 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004823 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004825 /* We have to initialize the server lookup mechanism depending
4826 * on what LB algorithm was choosen.
4827 */
4828
4829 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4830 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4831 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004832 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4833 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4834 init_server_map(curproxy);
4835 } else {
4836 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4837 fwrr_init_server_groups(curproxy);
4838 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004839 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004840
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004841 case BE_LB_KIND_LC:
4842 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004843 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004844 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004845
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004846 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004847 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4848 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4849 chash_init_server_tree(curproxy);
4850 } else {
4851 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4852 init_server_map(curproxy);
4853 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004854 break;
4855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856
4857 if (curproxy->options & PR_O_LOGASAP)
4858 curproxy->to_log &= ~LW_BYTES;
4859
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004860 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4861 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4862 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4863 proxy_type_str(curproxy), curproxy->id);
4864 err_code |= ERR_WARN;
4865 }
4866
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004868 * ensure that we're not cross-dressing a TCP server into HTTP.
4869 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004870 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004871 newsrv = curproxy->srv;
4872 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004873 if (!newsrv->puid) {
4874 /* server ID not set, use automatic numbering with first
4875 * spare entry starting with next_svid.
4876 */
4877 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4878 newsrv->conf.id.key = newsrv->puid = next_id;
4879 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4880 next_id++;
4881 }
4882
Willy Tarreau21d2af32008-02-14 20:25:24 +01004883 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004884 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4885 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004886 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004887 }
4888 newsrv = newsrv->next;
4889 }
4890
4891 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004892 * If this server supports a maxconn parameter, it needs a dedicated
4893 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004894 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895 */
4896 newsrv = curproxy->srv;
4897 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004898 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 /* Only 'minconn' was specified, or it was higher than or equal
4900 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4901 * this will avoid further useless expensive computations.
4902 */
4903 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004904 } else if (newsrv->maxconn && !newsrv->minconn) {
4905 /* minconn was not specified, so we set it to maxconn */
4906 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004907 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004908 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4909 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004910 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
4912
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004913 if (newsrv->trackit) {
4914 struct proxy *px;
4915 struct server *srv;
4916 char *pname, *sname;
4917
4918 pname = newsrv->trackit;
4919 sname = strrchr(pname, '/');
4920
4921 if (sname)
4922 *sname++ = '\0';
4923 else {
4924 sname = pname;
4925 pname = NULL;
4926 }
4927
4928 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004929 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004930 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004931 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4932 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004933 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004934 cfgerr++;
4935 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004936 }
4937 } else
4938 px = curproxy;
4939
4940 srv = findserver(px, sname);
4941 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004942 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4943 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004944 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004945 cfgerr++;
4946 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004947 }
4948
4949 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004950 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004951 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004952 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004953 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004954 cfgerr++;
4955 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004956 }
4957
4958 if (curproxy != px &&
4959 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004960 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004961 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004962 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004963 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004964 cfgerr++;
4965 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004966 }
4967
4968 newsrv->tracked = srv;
4969 newsrv->tracknext = srv->tracknext;
4970 srv->tracknext = newsrv;
4971
4972 free(newsrv->trackit);
4973 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004974 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 newsrv = newsrv->next;
4976 }
4977
Willy Tarreauc1a21672009-08-16 22:37:44 +02004978 if (curproxy->cap & PR_CAP_FE) {
4979 if (curproxy->tcp_req.inspect_delay ||
4980 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4981 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4982
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004983 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004984 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004985 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004986 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004987
4988 /* both TCP and HTTP must check switching rules */
4989 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4990 }
4991
4992 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004993 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004994 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004995 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004996 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004997
Emeric Brunb982a3d2010-01-04 15:45:53 +01004998 /* init table on backend capabilities proxy */
4999 stktable_init(&curproxy->table);
5000
Willy Tarreauc1a21672009-08-16 22:37:44 +02005001 /* If the backend does requires RDP cookie persistence, we have to
5002 * enable the corresponding analyser.
5003 */
5004 if (curproxy->options2 & PR_O2_RDPC_PRST)
5005 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5006 }
5007
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005008 listener = NULL;
5009 while (curproxy->listen) {
5010 struct listener *next;
5011
5012 next = curproxy->listen->next;
5013 curproxy->listen->next = listener;
5014 listener = curproxy->listen;
5015
5016 if (!next)
5017 break;
5018
5019 curproxy->listen = next;
5020 }
5021
Willy Tarreaue6b98942007-10-29 01:09:36 +01005022 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005023 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005024 listener = curproxy->listen;
5025 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005026 if (!listener->luid) {
5027 /* listener ID not set, use automatic numbering with first
5028 * spare entry starting with next_luid.
5029 */
5030 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5031 listener->conf.id.key = listener->luid = next_id;
5032 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
5033 next_id++;
5034 }
5035
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005036 /* enable separate counters */
5037 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5038 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5039 if (!listener->name) {
5040 sprintf(trash, "sock-%d", listener->luid);
5041 listener->name = strdup(trash);
5042 }
5043 }
5044
Willy Tarreaue6b98942007-10-29 01:09:36 +01005045 if (curproxy->options & PR_O_TCP_NOLING)
5046 listener->options |= LI_O_NOLINGER;
5047 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005048 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005049 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005050 listener->accept = event_accept;
5051 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005052 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005053 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005054
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005055 /* smart accept mode is automatic in HTTP mode */
5056 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5057 (curproxy->mode == PR_MODE_HTTP &&
5058 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5059 listener->options |= LI_O_NOQUICKACK;
5060
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005061 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005062 listener = listener->next;
5063 }
5064
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 curproxy = curproxy->next;
5066 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005067
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005068 /*
5069 * Recount currently required checks.
5070 */
5071
5072 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5073 int optnum;
5074
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005075 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5076 if (curproxy->options & cfg_opts[optnum].val)
5077 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005078
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005079 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5080 if (curproxy->options2 & cfg_opts2[optnum].val)
5081 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005082 }
5083
Willy Tarreaubb925012009-07-23 13:36:36 +02005084 if (cfgerr > 0)
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 out:
5087 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088}
5089
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005090/*
5091 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5092 * parsing sessions.
5093 */
5094void cfg_register_keywords(struct cfg_kw_list *kwl)
5095{
5096 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5097}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005099/*
5100 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5101 */
5102void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5103{
5104 LIST_DEL(&kwl->list);
5105 LIST_INIT(&kwl->list);
5106}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107
5108/*
5109 * Local variables:
5110 * c-indent-level: 8
5111 * c-basic-offset: 8
5112 * End:
5113 */