blob: 10013fe46bb36e02af0c3b8a9f9656e01b6a7d3a [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020043#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020045#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020046#include <proto/lb_fwlc.h>
47#include <proto/lb_fwrr.h>
48#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020050#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010051#include <proto/protocols.h>
52#include <proto/proto_tcp.h>
53#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010054#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010056#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/task.h>
58
59
Willy Tarreauf3c69202006-07-09 16:42:34 +020060/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
61 * ssl-hello-chk option to ensure that the remote server speaks SSL.
62 *
63 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
64 */
65const char sslv3_client_hello_pkt[] = {
66 "\x16" /* ContentType : 0x16 = Hanshake */
67 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
68 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
69 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
70 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
71 "\x03\x00" /* Hello Version : 0x0300 = v3 */
72 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
73 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
74 "\x00" /* Session ID length : empty (no session ID) */
75 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
76 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
77 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
78 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
79 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
80 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
81 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
82 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
83 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
84 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
85 "\x00\x38" "\x00\x39" "\x00\x3A"
86 "\x01" /* Compression Length : 0x01 = 1 byte for types */
87 "\x00" /* Compression Type : 0x00 = NULL compression */
88};
89
Willy Tarreau3842f002009-06-14 11:39:52 +020090/* various keyword modifiers */
91enum kw_mod {
92 KWM_STD = 0, /* normal */
93 KWM_NO, /* "no" prefixed before the keyword */
94 KWM_DEF, /* "default" prefixed before the keyword */
95};
96
Willy Tarreau13943ab2006-12-31 00:24:10 +010097/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010098struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010099 const char *name;
100 unsigned int val;
101 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100102 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100103};
104
105/* proxy->options */
106static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
113 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100114 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
116 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
117 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100118 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100119 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
120 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100121 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
123 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100124#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100125 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100126#endif
127
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100128 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100129};
130
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100131/* proxy->options2 */
132static const struct cfg_opt cfg_opts2[] =
133{
134#ifdef CONFIG_HAP_LINUX_SPLICE
135 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
136 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
137 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
138#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200139 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
140 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200141 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
142 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200143 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200144 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200145 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200146 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200147 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148 { NULL, 0, 0, 0 }
149};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200150
Willy Tarreau6daf3432008-01-22 16:44:08 +0100151static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200152static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
153int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100154int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200156/* List head of all known configuration keywords */
157static struct cfg_kw_list cfg_keywords = {
158 .list = LIST_HEAD_INIT(cfg_keywords.list)
159};
160
Willy Tarreaubaaee002006-06-26 02:48:02 +0200161/*
162 * converts <str> to a list of listeners which are dynamically allocated.
163 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
164 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
165 * - <port> is a numerical port from 1 to 65535 ;
166 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
167 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200168 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200170static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171{
172 struct listener *l;
173 char *c, *next, *range, *dupstr;
174 int port, end;
175
176 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200177
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178 while (next && *next) {
179 struct sockaddr_storage ss;
180
181 str = next;
182 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100183 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184 *next++ = 0;
185 }
186
187 /* 2) look for the addr/port delimiter, it's the last colon. */
188 if ((range = strrchr(str, ':')) == NULL) {
189 Alert("Missing port number: '%s'\n", str);
190 goto fail;
191 }
192
193 *range++ = 0;
194
195 if (strrchr(str, ':') != NULL) {
196 /* IPv6 address contains ':' */
197 memset(&ss, 0, sizeof(ss));
198 ss.ss_family = AF_INET6;
199
200 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
201 Alert("Invalid server address: '%s'\n", str);
202 goto fail;
203 }
204 }
205 else {
206 memset(&ss, 0, sizeof(ss));
207 ss.ss_family = AF_INET;
208
209 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
210 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
211 }
212 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
213 struct hostent *he;
214
215 if ((he = gethostbyname(str)) == NULL) {
216 Alert("Invalid server name: '%s'\n", str);
217 goto fail;
218 }
219 else
220 ((struct sockaddr_in *)&ss)->sin_addr =
221 *(struct in_addr *) *(he->h_addr_list);
222 }
223 }
224
225 /* 3) look for the port-end delimiter */
226 if ((c = strchr(range, '-')) != NULL) {
227 *c++ = 0;
228 end = atol(c);
229 }
230 else {
231 end = atol(range);
232 }
233
234 port = atol(range);
235
236 if (port < 1 || port > 65535) {
237 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
238 goto fail;
239 }
240
241 if (end < 1 || end > 65535) {
242 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
243 goto fail;
244 }
245
246 for (; port <= end; port++) {
247 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200248 l->next = curproxy->listen;
249 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
251 l->fd = -1;
252 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100253 l->state = LI_INIT;
254
255 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 tcpv6_add_listener(l);
258 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100260 tcpv4_add_listener(l);
261 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200262
Willy Tarreaue6b98942007-10-29 01:09:36 +0100263 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 } /* end for(port) */
265 } /* end while(next) */
266 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200267 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 fail:
269 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200270 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271}
272
Willy Tarreau977b8e42006-12-29 14:19:17 +0100273/*
274 * Sends a warning if proxy <proxy> does not have at least one of the
275 * capabilities in <cap>. An optionnal <hint> may be added at the end
276 * of the warning to help the user. Returns 1 if a warning was emitted
277 * or 0 if the condition is valid.
278 */
279int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
280{
281 char *msg;
282
283 switch (cap) {
284 case PR_CAP_BE: msg = "no backend"; break;
285 case PR_CAP_FE: msg = "no frontend"; break;
286 case PR_CAP_RS: msg = "no ruleset"; break;
287 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
288 default: msg = "not enough"; break;
289 }
290
291 if (!(proxy->cap & cap)) {
292 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100293 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100294 return 1;
295 }
296 return 0;
297}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298
Willy Tarreau61d18892009-03-31 10:49:21 +0200299/* Report a warning if a rule is placed after a 'block' rule.
300 * Return 1 if the warning has been emitted, otherwise 0.
301 */
302int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
303{
304 if (!LIST_ISEMPTY(&proxy->block_cond)) {
305 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
306 file, line, arg);
307 return 1;
308 }
309 return 0;
310}
311
312/* Report a warning if a rule is placed after a reqrewrite rule.
313 * Return 1 if the warning has been emitted, otherwise 0.
314 */
315int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
316{
317 if (proxy->req_exp) {
318 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
319 file, line, arg);
320 return 1;
321 }
322 return 0;
323}
324
325/* Report a warning if a rule is placed after a reqadd rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
328int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
329{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100330 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a redirect rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
341int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
342{
343 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a 'use_backend' rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
354int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
355{
356 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* report a warning if a block rule is dangerously placed */
365int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
366{
367 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
368 warnif_rule_after_reqadd(proxy, file, line, arg) ||
369 warnif_rule_after_redirect(proxy, file, line, arg) ||
370 warnif_rule_after_use_backend(proxy, file, line, arg);
371}
372
373/* report a warning if a reqxxx rule is dangerously placed */
374int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
375{
376 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
377 warnif_rule_after_redirect(proxy, file, line, arg) ||
378 warnif_rule_after_use_backend(proxy, file, line, arg);
379}
380
381/* report a warning if a reqadd rule is dangerously placed */
382int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
383{
384 return warnif_rule_after_redirect(proxy, file, line, arg) ||
385 warnif_rule_after_use_backend(proxy, file, line, arg);
386}
387
Willy Tarreaubaaee002006-06-26 02:48:02 +0200388/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200389 * parse a line in a <global> section. Returns the error code, 0 if OK, or
390 * any combination of :
391 * - ERR_ABORT: must abort ASAP
392 * - ERR_FATAL: we can continue parsing but not start the service
393 * - ERR_WARN: a warning has been emitted
394 * - ERR_ALERT: an alert has been emitted
395 * Only the two first ones can stop processing, the two others are just
396 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200397 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200398int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200399{
Willy Tarreau058e9072009-07-20 09:30:05 +0200400 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401
402 if (!strcmp(args[0], "global")) { /* new section */
403 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200405 }
406 else if (!strcmp(args[0], "daemon")) {
407 global.mode |= MODE_DAEMON;
408 }
409 else if (!strcmp(args[0], "debug")) {
410 global.mode |= MODE_DEBUG;
411 }
412 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100413 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200414 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200415 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100416 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200417 }
418 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100419 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200421 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100422 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200423 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100424 else if (!strcmp(args[0], "nosplice")) {
425 global.tune.options &= ~GTUNE_USE_SPLICE;
426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427 else if (!strcmp(args[0], "quiet")) {
428 global.mode |= MODE_QUIET;
429 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200430 else if (!strcmp(args[0], "tune.maxpollevents")) {
431 if (global.tune.maxpollevents != 0) {
432 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200433 err_code |= ERR_ALERT;
434 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200435 }
436 if (*(args[1]) == 0) {
437 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200438 err_code |= ERR_ALERT | ERR_FATAL;
439 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200440 }
441 global.tune.maxpollevents = atol(args[1]);
442 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100443 else if (!strcmp(args[0], "tune.maxaccept")) {
444 if (global.tune.maxaccept != 0) {
445 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 err_code |= ERR_ALERT;
447 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100448 }
449 if (*(args[1]) == 0) {
450 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200451 err_code |= ERR_ALERT | ERR_FATAL;
452 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100453 }
454 global.tune.maxaccept = atol(args[1]);
455 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200456 else if (!strcmp(args[0], "tune.bufsize")) {
457 if (*(args[1]) == 0) {
458 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
459 err_code |= ERR_ALERT | ERR_FATAL;
460 goto out;
461 }
462 global.tune.bufsize = atol(args[1]);
463 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
464 global.tune.maxrewrite = global.tune.bufsize / 2;
465 }
466 else if (!strcmp(args[0], "tune.maxrewrite")) {
467 if (*(args[1]) == 0) {
468 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
469 err_code |= ERR_ALERT | ERR_FATAL;
470 goto out;
471 }
472 global.tune.maxrewrite = atol(args[1]);
473 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
474 global.tune.maxrewrite = global.tune.bufsize / 2;
475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 else if (!strcmp(args[0], "uid")) {
477 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200478 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200479 err_code |= ERR_ALERT;
480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 }
482 if (*(args[1]) == 0) {
483 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200484 err_code |= ERR_ALERT | ERR_FATAL;
485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 }
487 global.uid = atol(args[1]);
488 }
489 else if (!strcmp(args[0], "gid")) {
490 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200491 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT;
493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494 }
495 if (*(args[1]) == 0) {
496 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200497 err_code |= ERR_ALERT | ERR_FATAL;
498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
500 global.gid = atol(args[1]);
501 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200502 /* user/group name handling */
503 else if (!strcmp(args[0], "user")) {
504 struct passwd *ha_user;
505 if (global.uid != 0) {
506 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT;
508 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200509 }
510 errno = 0;
511 ha_user = getpwnam(args[1]);
512 if (ha_user != NULL) {
513 global.uid = (int)ha_user->pw_uid;
514 }
515 else {
516 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200517 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200518 }
519 }
520 else if (!strcmp(args[0], "group")) {
521 struct group *ha_group;
522 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200523 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200524 err_code |= ERR_ALERT;
525 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200526 }
527 errno = 0;
528 ha_group = getgrnam(args[1]);
529 if (ha_group != NULL) {
530 global.gid = (int)ha_group->gr_gid;
531 }
532 else {
533 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200535 }
536 }
537 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "nbproc")) {
539 if (global.nbproc != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200541 err_code |= ERR_ALERT;
542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
549 global.nbproc = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "maxconn")) {
552 if (global.maxconn != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200554 err_code |= ERR_ALERT;
555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200561 }
562 global.maxconn = atol(args[1]);
563#ifdef SYSTEM_MAXCONN
564 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
565 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
566 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200567 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568 }
569#endif /* SYSTEM_MAXCONN */
570 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100571 else if (!strcmp(args[0], "maxpipes")) {
572 if (global.maxpipes != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200574 err_code |= ERR_ALERT;
575 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100581 }
582 global.maxpipes = atol(args[1]);
583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584 else if (!strcmp(args[0], "ulimit-n")) {
585 if (global.rlimit_nofile != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200587 err_code |= ERR_ALERT;
588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
595 global.rlimit_nofile = atol(args[1]);
596 }
597 else if (!strcmp(args[0], "chroot")) {
598 if (global.chroot != NULL) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200600 err_code |= ERR_ALERT;
601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 }
608 global.chroot = strdup(args[1]);
609 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200610 else if (!strcmp(args[0], "description")) {
611 int i, len=0;
612 char *d;
613
614 if (!*args[1]) {
615 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
616 file, linenum, args[0]);
617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
619 }
620
621 for(i=1; *args[i]; i++)
622 len += strlen(args[i])+1;
623
624 if (global.desc)
625 free(global.desc);
626
627 global.desc = d = (char *)calloc(1, len);
628
629 d += sprintf(d, "%s", args[1]);
630 for(i=2; *args[i]; i++)
631 d += sprintf(d, " %s", args[i]);
632 }
633 else if (!strcmp(args[0], "node")) {
634 int i;
635 char c;
636
637 for (i=0; args[1][i]; i++) {
638 c = args[1][i];
639 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
640 break;
641 }
642
643 if (!i || args[1][i]) {
644 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
645 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
646 file, linenum, args[0]);
647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
649 }
650
651 if (global.node)
652 free(global.node);
653
654 global.node = strdup(args[1]);
655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 else if (!strcmp(args[0], "pidfile")) {
657 if (global.pidfile != NULL) {
658 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT;
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
662 if (*(args[1]) == 0) {
663 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200664 err_code |= ERR_ALERT | ERR_FATAL;
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 }
667 global.pidfile = strdup(args[1]);
668 }
669 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100670 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200671 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672
673 if (*(args[1]) == 0 || *(args[2]) == 0) {
674 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 }
678
679 facility = get_log_facility(args[2]);
680 if (facility < 0) {
681 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
685
686 level = 7; /* max syslog level = debug */
687 if (*(args[3])) {
688 level = get_log_level(args[3]);
689 if (level < 0) {
690 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 }
695
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200696 minlvl = 0; /* limit syslog level to this level (emerg) */
697 if (*(args[4])) {
698 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200700 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200703 }
704 }
705
Robert Tsai81ae1952007-12-05 10:47:29 +0100706 if (args[1][0] == '/') {
707 logsrv.u.addr.sa_family = AF_UNIX;
708 logsrv.u.un = *str2sun(args[1]);
709 } else {
710 logsrv.u.addr.sa_family = AF_INET;
711 logsrv.u.in = *str2sa(args[1]);
712 if (!logsrv.u.in.sin_port)
713 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715
716 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100717 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 global.logfac1 = facility;
719 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200720 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100723 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 global.logfac2 = facility;
725 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200726 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 }
728 else {
729 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200732 }
733 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
734 if (global.spread_checks != 0) {
735 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT;
737 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200738 }
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200743 }
744 global.spread_checks = atol(args[1]);
745 if (global.spread_checks < 0 || global.spread_checks > 50) {
746 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200751 struct cfg_kw_list *kwl;
752 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200753 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200754
755 list_for_each_entry(kwl, &cfg_keywords.list, list) {
756 for (index = 0; kwl->kw[index].kw != NULL; index++) {
757 if (kwl->kw[index].section != CFG_GLOBAL)
758 continue;
759 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
760 /* prepare error message just in case */
761 snprintf(trash, sizeof(trash),
762 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200763 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
764 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200765 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200767 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200768 else if (rc > 0) {
769 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_WARN;
771 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200772 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200774 }
775 }
776 }
777
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200781
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 out:
783 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784}
785
Willy Tarreau97cb7802010-01-03 20:23:58 +0100786/* Perform the most basic initialization of a proxy :
787 * memset(), list_init(*), reset_timeouts(*).
788 */
789static void init_new_proxy(struct proxy *p)
790{
791 memset(p, 0, sizeof(struct proxy));
792 LIST_INIT(&p->pendconns);
793 LIST_INIT(&p->acl);
794 LIST_INIT(&p->block_cond);
795 LIST_INIT(&p->redirect_rules);
796 LIST_INIT(&p->mon_fail_cond);
797 LIST_INIT(&p->switching_rules);
798 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100799 LIST_INIT(&p->req_add);
800 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100801
802 /* Timeouts are defined as -1 */
803 proxy_reset_timeouts(p);
804}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200806void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100808 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 defproxy.mode = PR_MODE_TCP;
810 defproxy.state = PR_STNEW;
811 defproxy.maxconn = cfg_maxpconn;
812 defproxy.conn_retries = CONN_RETRIES;
813 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
814}
815
816/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100817 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200818 * Returns the error code, 0 if OK, or any combination of :
819 * - ERR_ABORT: must abort ASAP
820 * - ERR_FATAL: we can continue parsing but not start the service
821 * - ERR_WARN: a warning has been emitted
822 * - ERR_ALERT: an alert has been emitted
823 * Only the two first ones can stop processing, the two others are just
824 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200825 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200826int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827{
828 static struct proxy *curproxy = NULL;
829 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200830 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100831 int rc;
832 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200833 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834
Willy Tarreau977b8e42006-12-29 14:19:17 +0100835 if (!strcmp(args[0], "listen"))
836 rc = PR_CAP_LISTEN;
837 else if (!strcmp(args[0], "frontend"))
838 rc = PR_CAP_FE | PR_CAP_RS;
839 else if (!strcmp(args[0], "backend"))
840 rc = PR_CAP_BE | PR_CAP_RS;
841 else if (!strcmp(args[0], "ruleset"))
842 rc = PR_CAP_RS;
843 else
844 rc = PR_CAP_NONE;
845
846 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200847 if (!*args[1]) {
848 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
849 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
850 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200851 err_code |= ERR_ALERT | ERR_ABORT;
852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200854
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100855 err = invalid_char(args[1]);
856 if (err) {
857 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
858 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200859 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100860 }
861
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200862 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
863 /*
864 * If there are two proxies with the same name only following
865 * combinations are allowed:
866 *
867 * listen backend frontend ruleset
868 * listen - - - -
869 * backend - - OK -
870 * frontend - OK - -
871 * ruleset - - - -
872 */
873
874 if (!strcmp(curproxy->id, args[1]) &&
875 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
876 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200877 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
878 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
879 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200880 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200881 }
882 }
883
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
885 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200886 err_code |= ERR_ALERT | ERR_ABORT;
887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100889
Willy Tarreau97cb7802010-01-03 20:23:58 +0100890 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 curproxy->next = proxy;
892 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200893 curproxy->conf.file = file;
894 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200895 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100897 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898
899 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100900 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200901 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200902 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200903 err_code |= ERR_FATAL;
904 goto out;
905 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200906 new = curproxy->listen;
907 while (new != last) {
908 new->conf.file = file;
909 new->conf.line = linenum;
910 new = new->next;
911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 global.maxsock++;
913 }
914
915 /* set default values */
916 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100918 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200919 curproxy->no_options = defproxy.no_options;
920 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100921 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100922 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200923 curproxy->except_net = defproxy.except_net;
924 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200925 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200926 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200928 if (defproxy.fwdfor_hdr_len) {
929 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
930 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
931 }
932
Willy Tarreaub86db342009-11-30 11:50:16 +0100933 if (defproxy.orgto_hdr_len) {
934 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
935 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
936 }
937
Willy Tarreau977b8e42006-12-29 14:19:17 +0100938 if (curproxy->cap & PR_CAP_FE) {
939 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100940 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200941 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100942
943 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200944 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
945 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100946
947 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949
Willy Tarreau977b8e42006-12-29 14:19:17 +0100950 if (curproxy->cap & PR_CAP_BE) {
951 curproxy->fullconn = defproxy.fullconn;
952 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953
Willy Tarreau977b8e42006-12-29 14:19:17 +0100954 if (defproxy.check_req)
955 curproxy->check_req = strdup(defproxy.check_req);
956 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957
Willy Tarreau977b8e42006-12-29 14:19:17 +0100958 if (defproxy.cookie_name)
959 curproxy->cookie_name = strdup(defproxy.cookie_name);
960 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +0100961 if (defproxy.cookie_domain)
962 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +0100963
Emeric Brun647caf12009-06-30 17:57:00 +0200964 if (defproxy.rdp_cookie_name)
965 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
966 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
967
Willy Tarreau01732802007-11-01 22:48:15 +0100968 if (defproxy.url_param_name)
969 curproxy->url_param_name = strdup(defproxy.url_param_name);
970 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100971
Benoitaffb4812009-03-25 13:02:10 +0100972 if (defproxy.hh_name)
973 curproxy->hh_name = strdup(defproxy.hh_name);
974 curproxy->hh_len = defproxy.hh_len;
975 curproxy->hh_match_domain = defproxy.hh_match_domain;
976
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100977 if (defproxy.iface_name)
978 curproxy->iface_name = strdup(defproxy.iface_name);
979 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200982 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100983 if (defproxy.capture_name)
984 curproxy->capture_name = strdup(defproxy.capture_name);
985 curproxy->capture_namelen = defproxy.capture_namelen;
986 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988
Willy Tarreau977b8e42006-12-29 14:19:17 +0100989 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100990 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100991 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100992 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100993 curproxy->uri_auth = defproxy.uri_auth;
994 curproxy->mon_net = defproxy.mon_net;
995 curproxy->mon_mask = defproxy.mon_mask;
996 if (defproxy.monitor_uri)
997 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
998 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100999 if (defproxy.defbe.name)
1000 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001001 }
1002
1003 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001004 curproxy->timeout.connect = defproxy.timeout.connect;
1005 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001006 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001007 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001008 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001009 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001010 curproxy->source_addr = defproxy.source_addr;
1011 }
1012
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013 curproxy->mode = defproxy.mode;
1014 curproxy->logfac1 = defproxy.logfac1;
1015 curproxy->logsrv1 = defproxy.logsrv1;
1016 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001017 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001018 curproxy->logfac2 = defproxy.logfac2;
1019 curproxy->logsrv2 = defproxy.logsrv2;
1020 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001021 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001023 curproxy->conf.used_listener_id = EB_ROOT;
1024 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001025
Willy Tarreau93893792009-07-23 13:19:11 +02001026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027 }
1028 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1029 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001030 /* FIXME-20070101: we should do this too at the end of the
1031 * config parsing to free all default values.
1032 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001033 free(defproxy.check_req);
1034 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001035 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001036 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001037 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001038 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001039 free(defproxy.capture_name);
1040 free(defproxy.monitor_uri);
1041 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001042 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001043 free(defproxy.fwdfor_hdr_name);
1044 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001045 free(defproxy.orgto_hdr_name);
1046 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001047
Willy Tarreaua534fea2008-08-03 12:19:50 +02001048 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001049 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001050
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 /* we cannot free uri_auth because it might already be used */
1052 init_default_instance();
1053 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001054 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
1057 else if (curproxy == NULL) {
1058 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 }
1062
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063
1064 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001066 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001067 int cur_arg;
1068
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 if (curproxy == &defproxy) {
1070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001074 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001075 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076
1077 if (strchr(args[1], ':') == NULL) {
1078 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001083
1084 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001085 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001089
Willy Tarreau90a570f2009-10-04 20:54:54 +02001090 new_listen = curproxy->listen;
1091 while (new_listen != last_listen) {
1092 new_listen->conf.file = file;
1093 new_listen->conf.line = linenum;
1094 new_listen = new_listen->next;
1095 }
1096
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001097 cur_arg = 2;
1098 while (*(args[cur_arg])) {
1099 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1100#ifdef SO_BINDTODEVICE
1101 struct listener *l;
1102
1103 if (!*args[cur_arg + 1]) {
1104 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001108 }
1109
1110 for (l = curproxy->listen; l != last_listen; l = l->next)
1111 l->interface = strdup(args[cur_arg + 1]);
1112
1113 global.last_checks |= LSTCHK_NETADM;
1114
1115 cur_arg += 2;
1116 continue;
1117#else
1118 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1119 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001122#endif
1123 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001124 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1125#ifdef TCP_MAXSEG
1126 struct listener *l;
1127 int mss;
1128
1129 if (!*args[cur_arg + 1]) {
1130 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001134 }
1135
1136 mss = str2uic(args[cur_arg + 1]);
1137 if (mss < 1 || mss > 65535) {
1138 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1139 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001142 }
1143
1144 for (l = curproxy->listen; l != last_listen; l = l->next)
1145 l->maxseg = mss;
1146
1147 cur_arg += 2;
1148 continue;
1149#else
1150 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1151 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001154#endif
1155 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001156
1157 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1158#ifdef TCP_DEFER_ACCEPT
1159 struct listener *l;
1160
1161 for (l = curproxy->listen; l != last_listen; l = l->next)
1162 l->options |= LI_O_DEF_ACCEPT;
1163
1164 cur_arg ++;
1165 continue;
1166#else
1167 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1168 file, linenum, args[0], args[cur_arg]);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto out;
1171#endif
1172 }
1173
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001174 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001175#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001176 struct listener *l;
1177
1178 for (l = curproxy->listen; l != last_listen; l = l->next)
1179 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001180
1181 cur_arg ++;
1182 continue;
1183#else
1184 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1185 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001188#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001189 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001190
1191 if (!strcmp(args[cur_arg], "name")) {
1192 struct listener *l;
1193
1194 for (l = curproxy->listen; l != last_listen; l = l->next)
1195 l->name = strdup(args[cur_arg + 1]);
1196
1197 cur_arg += 2;
1198 continue;
1199 }
1200
1201 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001202 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001203 struct listener *l;
1204
1205 if (curproxy->listen->next != last_listen) {
1206 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1207 file, linenum, args[cur_arg]);
1208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
1210 }
1211
1212 if (!*args[cur_arg + 1]) {
1213 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1214 file, linenum, args[cur_arg]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218
1219 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001220 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001221
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001222 if (curproxy->listen->luid <= 0) {
1223 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001224 file, linenum);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001229 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1230 if (node) {
1231 l = container_of(node, struct listener, conf.id);
1232 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1233 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1238
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001239 cur_arg += 2;
1240 continue;
1241 }
1242
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001243 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 +01001244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 }
1251 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1252 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1253 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1254 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001258 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001260
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 /* flush useless bits */
1262 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001265 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001267 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001268
Willy Tarreau1c47f852006-07-09 08:22:27 +02001269 if (!*args[1]) {
1270 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001274 }
1275
Willy Tarreaua534fea2008-08-03 12:19:50 +02001276 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001277 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001278 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001279 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001280 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1281
Willy Tarreau93893792009-07-23 13:19:11 +02001282 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1285 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1286 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1287 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1288 else {
1289 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 }
1293 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001294 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001295 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001296
1297 if (curproxy == &defproxy) {
1298 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001302 }
1303
1304 if (!*args[1]) {
1305 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001307 err_code |= ERR_ALERT | ERR_FATAL;
1308 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001309 }
1310
1311 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001312 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001313
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001314 if (curproxy->uuid <= 0) {
1315 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001316 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001319 }
1320
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001321 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1322 if (node) {
1323 struct proxy *target = container_of(node, struct proxy, conf.id);
1324 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1325 file, linenum, proxy_type_str(curproxy), curproxy->id,
1326 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
1329 }
1330 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001331 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001332 else if (!strcmp(args[0], "description")) {
1333 int i, len=0;
1334 char *d;
1335
1336 if (!*args[1]) {
1337 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1338 file, linenum, args[0]);
1339 return -1;
1340 }
1341
1342 for(i=1; *args[i]; i++)
1343 len += strlen(args[i])+1;
1344
1345 d = (char *)calloc(1, len);
1346 curproxy->desc = d;
1347
1348 d += sprintf(d, "%s", args[1]);
1349 for(i=2; *args[i]; i++)
1350 d += sprintf(d, " %s", args[i]);
1351
1352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1354 curproxy->state = PR_STSTOPPED;
1355 }
1356 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1357 curproxy->state = PR_STNEW;
1358 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001359 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1360 int cur_arg = 1;
1361 unsigned int set = 0;
1362
1363 while (*args[cur_arg]) {
1364 int u;
1365 if (strcmp(args[cur_arg], "all") == 0) {
1366 set = 0;
1367 break;
1368 }
1369 else if (strcmp(args[cur_arg], "odd") == 0) {
1370 set |= 0x55555555;
1371 }
1372 else if (strcmp(args[cur_arg], "even") == 0) {
1373 set |= 0xAAAAAAAA;
1374 }
1375 else {
1376 u = str2uic(args[cur_arg]);
1377 if (u < 1 || u > 32) {
1378 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1379 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001382 }
1383 if (u > global.nbproc) {
1384 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1385 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001386 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001387 }
1388 set |= 1 << (u - 1);
1389 }
1390 cur_arg++;
1391 }
1392 curproxy->bind_proc = set;
1393 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001394 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001395 if (curproxy == &defproxy) {
1396 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001399 }
1400
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001401 err = invalid_char(args[1]);
1402 if (err) {
1403 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1404 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001406 }
1407
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001408 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1409 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1410 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001413 }
1414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1416 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417
Willy Tarreau977b8e42006-12-29 14:19:17 +01001418 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001419 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 if (*(args[1]) == 0) {
1422 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1423 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001424 err_code |= ERR_ALERT | ERR_FATAL;
1425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001427
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001428 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001429 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 curproxy->cookie_name = strdup(args[1]);
1431 curproxy->cookie_len = strlen(curproxy->cookie_name);
1432
1433 cur_arg = 2;
1434 while (*(args[cur_arg])) {
1435 if (!strcmp(args[cur_arg], "rewrite")) {
1436 curproxy->options |= PR_O_COOK_RW;
1437 }
1438 else if (!strcmp(args[cur_arg], "indirect")) {
1439 curproxy->options |= PR_O_COOK_IND;
1440 }
1441 else if (!strcmp(args[cur_arg], "insert")) {
1442 curproxy->options |= PR_O_COOK_INS;
1443 }
1444 else if (!strcmp(args[cur_arg], "nocache")) {
1445 curproxy->options |= PR_O_COOK_NOC;
1446 }
1447 else if (!strcmp(args[cur_arg], "postonly")) {
1448 curproxy->options |= PR_O_COOK_POST;
1449 }
1450 else if (!strcmp(args[cur_arg], "prefix")) {
1451 curproxy->options |= PR_O_COOK_PFX;
1452 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001453 else if (!strcmp(args[cur_arg], "domain")) {
1454 if (!*args[cur_arg + 1]) {
1455 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1456 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001459 }
1460
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001461 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001462 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001463 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1464 " dots nor does not start with a dot."
1465 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001466 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001467 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001468 }
1469
1470 err = invalid_domainchar(args[cur_arg + 1]);
1471 if (err) {
1472 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1473 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001476 }
1477
Willy Tarreau68a897b2009-12-03 23:28:34 +01001478 if (!curproxy->cookie_domain) {
1479 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1480 } else {
1481 /* one domain was already specified, add another one by
1482 * building the string which will be returned along with
1483 * the cookie.
1484 */
1485 char *new_ptr;
1486 int new_len = strlen(curproxy->cookie_domain) +
1487 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1488 new_ptr = malloc(new_len);
1489 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1490 free(curproxy->cookie_domain);
1491 curproxy->cookie_domain = new_ptr;
1492 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001493 cur_arg++;
1494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001496 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 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 }
1501 cur_arg++;
1502 }
1503 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1504 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 }
1508
1509 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1510 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1511 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001512 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513 }
1514 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001515 else if (!strcmp(args[0], "persist")) { /* persist */
1516 if (*(args[1]) == 0) {
1517 Alert("parsing [%s:%d] : missing persist method.\n",
1518 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001521 }
1522
1523 if (!strncmp(args[1], "rdp-cookie", 10)) {
1524 curproxy->options2 |= PR_O2_RDPC_PRST;
1525
1526 if (*(args[1] + 10 ) == '(') { /* cookie name */
1527 const char *beg, *end;
1528
1529 beg = args[1] + 11;
1530 end = strchr(beg, ')');
1531
1532 if (!end || end == beg) {
1533 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001535 err_code |= ERR_ALERT | ERR_FATAL;
1536 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001537 }
1538
1539 free(curproxy->rdp_cookie_name);
1540 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1541 curproxy->rdp_cookie_len = end-beg;
1542 }
1543 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1544 free(curproxy->rdp_cookie_name);
1545 curproxy->rdp_cookie_name = strdup("msts");
1546 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1547 }
1548 else { /* syntax */
1549 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1550 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001553 }
1554 }
1555 else {
1556 Alert("parsing [%s:%d] : unknown persist method.\n",
1557 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001558 err_code |= ERR_ALERT | ERR_FATAL;
1559 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001560 }
1561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001563 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564
Willy Tarreau977b8e42006-12-29 14:19:17 +01001565 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001566 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001569 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 }
1574 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001575 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 curproxy->appsession_name = strdup(args[1]);
1577 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1578 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001579 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1580 if (err) {
1581 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1582 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001583 err_code |= ERR_ALERT | ERR_FATAL;
1584 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001585 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001586 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001587
Willy Tarreau51041c72007-09-09 21:56:53 +02001588 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001590 err_code |= ERR_ALERT | ERR_ABORT;
1591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001593
1594 cur_arg = 6;
1595 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001596 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1597 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001598 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001599 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001600 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001601 } else if (!strcmp(args[cur_arg], "prefix")) {
1602 curproxy->options2 |= PR_O2_AS_PFX;
1603 } else if (!strcmp(args[cur_arg], "mode")) {
1604 if (!*args[cur_arg + 1]) {
1605 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1606 file, linenum, args[0], args[cur_arg]);
1607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
1609 }
1610
1611 cur_arg++;
1612 if (!strcmp(args[cur_arg], "query-string")) {
1613 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1614 curproxy->options2 |= PR_O2_AS_M_QS;
1615 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1616 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1617 curproxy->options2 |= PR_O2_AS_M_PP;
1618 } else {
1619 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001624 cur_arg++;
1625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 } /* Url App Session */
1627 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001628 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001630
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 if (*(args[4]) == 0) {
1633 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001638 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 curproxy->capture_name = strdup(args[2]);
1640 curproxy->capture_namelen = strlen(curproxy->capture_name);
1641 curproxy->capture_len = atol(args[4]);
1642 if (curproxy->capture_len >= CAPTURE_LEN) {
1643 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1644 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 curproxy->capture_len = CAPTURE_LEN - 1;
1647 }
1648 curproxy->to_log |= LW_COOKIE;
1649 }
1650 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1651 struct cap_hdr *hdr;
1652
1653 if (curproxy == &defproxy) {
1654 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 +02001655 err_code |= ERR_ALERT | ERR_FATAL;
1656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 }
1658
1659 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1660 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1661 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
1665
1666 hdr = calloc(sizeof(struct cap_hdr), 1);
1667 hdr->next = curproxy->req_cap;
1668 hdr->name = strdup(args[3]);
1669 hdr->namelen = strlen(args[3]);
1670 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001671 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 hdr->index = curproxy->nb_req_cap++;
1673 curproxy->req_cap = hdr;
1674 curproxy->to_log |= LW_REQHDR;
1675 }
1676 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1677 struct cap_hdr *hdr;
1678
1679 if (curproxy == &defproxy) {
1680 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 +02001681 err_code |= ERR_ALERT | ERR_FATAL;
1682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 }
1684
1685 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1686 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1687 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
1691 hdr = calloc(sizeof(struct cap_hdr), 1);
1692 hdr->next = curproxy->rsp_cap;
1693 hdr->name = strdup(args[3]);
1694 hdr->namelen = strlen(args[3]);
1695 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001696 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 hdr->index = curproxy->nb_rsp_cap++;
1698 curproxy->rsp_cap = hdr;
1699 curproxy->to_log |= LW_RSPHDR;
1700 }
1701 else {
1702 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1703 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 }
1707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 if (*(args[1]) == 0) {
1713 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\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 }
1718 curproxy->conn_retries = atol(args[1]);
1719 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001720 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1721 int pol = ACL_COND_NONE;
1722 struct acl_cond *cond;
1723
Willy Tarreaub099aca2008-10-12 17:26:37 +02001724 if (curproxy == &defproxy) {
1725 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001728 }
1729
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001730 if (!strcmp(args[1], "if"))
1731 pol = ACL_COND_IF;
1732 else if (!strcmp(args[1], "unless"))
1733 pol = ACL_COND_UNLESS;
1734
1735 if (pol == ACL_COND_NONE) {
1736 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001740 }
1741
1742 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1743 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1744 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001747 }
Willy Tarreau88922352009-10-04 22:02:50 +02001748 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001749 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001750 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001751 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001752 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001753 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001754 else if (!strcmp(args[0], "redirect")) {
1755 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001756 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001757 struct redirect_rule *rule;
1758 int cur_arg;
1759 int type = REDIRECT_TYPE_NONE;
1760 int code = 302;
1761 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001762 char *cookie = NULL;
1763 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001764 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001765
1766 cur_arg = 1;
1767 while (*(args[cur_arg])) {
1768 if (!strcmp(args[cur_arg], "location")) {
1769 if (!*args[cur_arg + 1]) {
1770 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1771 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001774 }
1775
1776 type = REDIRECT_TYPE_LOCATION;
1777 cur_arg++;
1778 destination = args[cur_arg];
1779 }
1780 else if (!strcmp(args[cur_arg], "prefix")) {
1781 if (!*args[cur_arg + 1]) {
1782 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1783 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001786 }
1787
1788 type = REDIRECT_TYPE_PREFIX;
1789 cur_arg++;
1790 destination = args[cur_arg];
1791 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001792 else if (!strcmp(args[cur_arg], "set-cookie")) {
1793 if (!*args[cur_arg + 1]) {
1794 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1795 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001798 }
1799
1800 cur_arg++;
1801 cookie = args[cur_arg];
1802 cookie_set = 1;
1803 }
1804 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1805 if (!*args[cur_arg + 1]) {
1806 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1807 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001810 }
1811
1812 cur_arg++;
1813 cookie = args[cur_arg];
1814 cookie_set = 0;
1815 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001816 else if (!strcmp(args[cur_arg],"code")) {
1817 if (!*args[cur_arg + 1]) {
1818 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1819 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001822 }
1823 cur_arg++;
1824 code = atol(args[cur_arg]);
1825 if (code < 301 || code > 303) {
1826 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1827 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001828 err_code |= ERR_ALERT | ERR_FATAL;
1829 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001830 }
1831 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001832 else if (!strcmp(args[cur_arg],"drop-query")) {
1833 flags |= REDIRECT_FLAG_DROP_QS;
1834 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001835 else if (!strcmp(args[cur_arg], "if")) {
1836 pol = ACL_COND_IF;
1837 cur_arg++;
1838 break;
1839 }
1840 else if (!strcmp(args[cur_arg], "unless")) {
1841 pol = ACL_COND_UNLESS;
1842 cur_arg++;
1843 break;
1844 }
1845 else {
Willy Tarreau963abc32010-01-03 19:47:39 +01001846 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie' or 'drop-query' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001847 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001850 }
1851 cur_arg++;
1852 }
1853
1854 if (type == REDIRECT_TYPE_NONE) {
1855 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1856 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001859 }
1860
Willy Tarreauf285f542010-01-03 20:03:03 +01001861 if (pol != ACL_COND_NONE &&
1862 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001863 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001864 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001867 }
1868
Willy Tarreauf285f542010-01-03 20:03:03 +01001869 if (cond) {
1870 cond->file = file;
1871 cond->line = linenum;
1872 curproxy->acl_requires |= cond->requires;
1873 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001874 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1875 rule->cond = cond;
1876 rule->rdr_str = strdup(destination);
1877 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001878 if (cookie) {
1879 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1880 * a clear consists in appending "; Max-Age=0" at the end.
1881 */
1882 rule->cookie_len = strlen(cookie);
1883 if (cookie_set)
1884 rule->cookie_str = strdup(cookie);
1885 else {
1886 rule->cookie_str = malloc(rule->cookie_len + 12);
1887 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1888 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1889 rule->cookie_len += 11;
1890 }
1891 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001892 rule->type = type;
1893 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001894 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001895 LIST_INIT(&rule->list);
1896 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001897 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001898 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001899 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001900 int pol = ACL_COND_NONE;
1901 struct acl_cond *cond;
1902 struct switching_rule *rule;
1903
Willy Tarreaub099aca2008-10-12 17:26:37 +02001904 if (curproxy == &defproxy) {
1905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001908 }
1909
Willy Tarreau55ea7572007-06-17 19:56:27 +02001910 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001911 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001912
1913 if (*(args[1]) == 0) {
1914 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001917 }
1918
1919 if (!strcmp(args[2], "if"))
1920 pol = ACL_COND_IF;
1921 else if (!strcmp(args[2], "unless"))
1922 pol = ACL_COND_UNLESS;
1923
1924 if (pol == ACL_COND_NONE) {
1925 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1926 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001929 }
1930
1931 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001932 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001933 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001936 }
1937
Willy Tarreau88922352009-10-04 22:02:50 +02001938 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001939 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001940 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001941 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001942 struct acl *acl;
1943 const char *name;
1944
1945 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1946 name = acl ? acl->name : "(unknown)";
1947 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1948 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001950 }
1951
Willy Tarreau55ea7572007-06-17 19:56:27 +02001952 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1953 rule->cond = cond;
1954 rule->be.name = strdup(args[1]);
1955 LIST_INIT(&rule->list);
1956 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1963 curproxy->uri_auth = NULL; /* we must detach from the default config */
1964
1965 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001966 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable', 'hide-version', 'show-node', 'show-desc'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 } else if (!strcmp(args[1], "uri")) {
1970 if (*(args[2]) == 0) {
1971 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001972 err_code |= ERR_ALERT | ERR_FATAL;
1973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1975 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_ALERT | ERR_ABORT;
1977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 }
1979 } else if (!strcmp(args[1], "realm")) {
1980 if (*(args[2]) == 0) {
1981 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001982 err_code |= ERR_ALERT | ERR_FATAL;
1983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1985 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001986 err_code |= ERR_ALERT | ERR_ABORT;
1987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001989 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001990 unsigned interval;
1991
1992 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1993 if (err) {
1994 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1995 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001996 err_code |= ERR_ALERT | ERR_FATAL;
1997 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001998 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1999 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_ABORT;
2001 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 } else if (!strcmp(args[1], "auth")) {
2004 if (*(args[2]) == 0) {
2005 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2009 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_ABORT;
2011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 }
2013 } else if (!strcmp(args[1], "scope")) {
2014 if (*(args[2]) == 0) {
2015 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2019 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_ABORT;
2021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 }
2023 } else if (!strcmp(args[1], "enable")) {
2024 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2025 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_ALERT | ERR_ABORT;
2027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002029 } else if (!strcmp(args[1], "hide-version")) {
2030 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2031 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_ABORT;
2033 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002034 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002035 } else if (!strcmp(args[1], "show-node")) {
2036
2037 if (*args[2]) {
2038 int i;
2039 char c;
2040
2041 for (i=0; args[2][i]; i++) {
2042 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002043 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002044 break;
2045 }
2046
2047 if (!i || args[2][i]) {
2048 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2049 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2050 file, linenum, args[0], args[1]);
2051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
2053 }
2054 }
2055
2056 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2057 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2058 err_code |= ERR_ALERT | ERR_ABORT;
2059 goto out;
2060 }
2061 } else if (!strcmp(args[1], "show-desc")) {
2062 char *desc = NULL;
2063
2064 if (*args[2]) {
2065 int i, len=0;
2066 char *d;
2067
2068 for(i=2; *args[i]; i++)
2069 len += strlen(args[i])+1;
2070
2071 desc = d = (char *)calloc(1, len);
2072
2073 d += sprintf(d, "%s", args[2]);
2074 for(i=3; *args[i]; i++)
2075 d += sprintf(d, " %s", args[i]);
2076 }
2077
2078 if (!*args[2] && !global.desc)
2079 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2080 file, linenum, args[1]);
2081 else {
2082 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2083 free(desc);
2084 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2085 err_code |= ERR_ALERT | ERR_ABORT;
2086 goto out;
2087 }
2088 free(desc);
2089 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002091 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 }
2096 }
2097 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002098 int optnum;
2099
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002100 if (*(args[1]) == '\0') {
2101 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002106
2107 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2108 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002109 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2110 err_code |= ERR_WARN;
2111 goto out;
2112 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002113
Willy Tarreau3842f002009-06-14 11:39:52 +02002114 curproxy->no_options &= ~cfg_opts[optnum].val;
2115 curproxy->options &= ~cfg_opts[optnum].val;
2116
2117 switch (kwm) {
2118 case KWM_STD:
2119 curproxy->options |= cfg_opts[optnum].val;
2120 break;
2121 case KWM_NO:
2122 curproxy->no_options |= cfg_opts[optnum].val;
2123 break;
2124 case KWM_DEF: /* already cleared */
2125 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002126 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002127
Willy Tarreau93893792009-07-23 13:19:11 +02002128 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002129 }
2130 }
2131
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002132 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2133 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002134 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2135 err_code |= ERR_WARN;
2136 goto out;
2137 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002138
Willy Tarreau3842f002009-06-14 11:39:52 +02002139 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2140 curproxy->options2 &= ~cfg_opts2[optnum].val;
2141
2142 switch (kwm) {
2143 case KWM_STD:
2144 curproxy->options2 |= cfg_opts2[optnum].val;
2145 break;
2146 case KWM_NO:
2147 curproxy->no_options2 |= cfg_opts2[optnum].val;
2148 break;
2149 case KWM_DEF: /* already cleared */
2150 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002151 }
Willy Tarreau93893792009-07-23 13:19:11 +02002152 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002153 }
2154 }
2155
Willy Tarreau3842f002009-06-14 11:39:52 +02002156 if (kwm != KWM_STD) {
2157 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002158 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002161 }
2162
Emeric Brun3a058f32009-06-30 18:26:00 +02002163 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002165 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002166 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002167 if (*(args[2]) != '\0') {
2168 if (!strcmp(args[2], "clf")) {
2169 curproxy->options2 |= PR_O2_CLFLOG;
2170 } else {
2171 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_ALERT | ERR_FATAL;
2173 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002174 }
2175 }
2176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 else if (!strcmp(args[1], "tcplog"))
2178 /* generate a detailed TCP log */
2179 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180 else if (!strcmp(args[1], "tcpka")) {
2181 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002182 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002183 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002184
2185 if (curproxy->cap & PR_CAP_FE)
2186 curproxy->options |= PR_O_TCP_CLI_KA;
2187 if (curproxy->cap & PR_CAP_BE)
2188 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
2190 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002192 err_code |= ERR_WARN;
2193
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002195 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002196 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002197 curproxy->options &= ~PR_O_SMTP_CHK;
2198 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 if (!*args[2]) { /* no argument */
2200 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2201 curproxy->check_len = strlen(DEF_CHECK_REQ);
2202 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002203 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 curproxy->check_req = (char *)malloc(reqlen);
2205 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2206 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2207 } else { /* more arguments : METHOD URI [HTTP_VER] */
2208 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2209 if (*args[4])
2210 reqlen += strlen(args[4]);
2211 else
2212 reqlen += strlen("HTTP/1.0");
2213
2214 curproxy->check_req = (char *)malloc(reqlen);
2215 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2216 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2217 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002218 }
2219 else if (!strcmp(args[1], "ssl-hello-chk")) {
2220 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002221 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002223
Willy Tarreaua534fea2008-08-03 12:19:50 +02002224 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002225 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002226 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002227 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 }
Willy Tarreau23677902007-05-08 23:50:35 +02002229 else if (!strcmp(args[1], "smtpchk")) {
2230 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002231 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002232 curproxy->options &= ~PR_O_HTTP_CHK;
2233 curproxy->options &= ~PR_O_SSL3_CHK;
2234 curproxy->options |= PR_O_SMTP_CHK;
2235
2236 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2237 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2238 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2239 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2240 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2241 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2242 curproxy->check_req = (char *)malloc(reqlen);
2243 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2244 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2245 } else {
2246 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2247 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2248 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2249 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2250 }
2251 }
2252 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002253 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002254 int cur_arg;
2255
2256 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2257 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002258 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002259
2260 curproxy->options |= PR_O_FWDFOR;
2261
2262 free(curproxy->fwdfor_hdr_name);
2263 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2264 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2265
2266 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2267 cur_arg = 2;
2268 while (*(args[cur_arg])) {
2269 if (!strcmp(args[cur_arg], "except")) {
2270 /* suboption except - needs additional argument for it */
2271 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2272 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2273 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002276 }
2277 /* flush useless bits */
2278 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002279 cur_arg += 2;
2280 } else if (!strcmp(args[cur_arg], "header")) {
2281 /* suboption header - needs additional argument for it */
2282 if (*(args[cur_arg+1]) == 0) {
2283 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2284 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002287 }
2288 free(curproxy->fwdfor_hdr_name);
2289 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2290 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2291 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002292 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002293 /* unknown suboption - catchall */
2294 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2295 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002298 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002299 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002300 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002301 else if (!strcmp(args[1], "originalto")) {
2302 int cur_arg;
2303
2304 /* insert x-original-to field, but not for the IP address listed as an except.
2305 * set default options (ie: bitfield, header name, etc)
2306 */
2307
2308 curproxy->options |= PR_O_ORGTO;
2309
2310 free(curproxy->orgto_hdr_name);
2311 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2312 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2313
2314 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2315 cur_arg = 2;
2316 while (*(args[cur_arg])) {
2317 if (!strcmp(args[cur_arg], "except")) {
2318 /* suboption except - needs additional argument for it */
2319 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2320 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2321 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002324 }
2325 /* flush useless bits */
2326 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2327 cur_arg += 2;
2328 } else if (!strcmp(args[cur_arg], "header")) {
2329 /* suboption header - needs additional argument for it */
2330 if (*(args[cur_arg+1]) == 0) {
2331 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2332 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002335 }
2336 free(curproxy->orgto_hdr_name);
2337 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2338 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2339 cur_arg += 2;
2340 } else {
2341 /* unknown suboption - catchall */
2342 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2343 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002346 }
2347 } /* end while loop */
2348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 else {
2350 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
Willy Tarreau93893792009-07-23 13:19:11 +02002354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002356 else if (!strcmp(args[0], "default_backend")) {
2357 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002359
2360 if (*(args[1]) == 0) {
2361 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002364 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002365 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002366 curproxy->defbe.name = strdup(args[1]);
2367 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002372 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 /* enable reconnections to dispatch */
2376 curproxy->options |= PR_O_REDISP;
2377 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002378 else if (!strcmp(args[0], "http-check")) {
2379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002381
2382 if (strcmp(args[1], "disable-on-404") == 0) {
2383 /* enable a graceful server shutdown on an HTTP 404 response */
2384 curproxy->options |= PR_O_DISABLE404;
2385 }
2386 else {
2387 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002390 }
2391 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002392 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002393 if (curproxy == &defproxy) {
2394 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002397 }
2398
Willy Tarreaub80c2302007-11-30 20:51:32 +01002399 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002401
2402 if (strcmp(args[1], "fail") == 0) {
2403 /* add a condition to fail monitor requests */
2404 int pol = ACL_COND_NONE;
2405 struct acl_cond *cond;
2406
2407 if (!strcmp(args[2], "if"))
2408 pol = ACL_COND_IF;
2409 else if (!strcmp(args[2], "unless"))
2410 pol = ACL_COND_UNLESS;
2411
2412 if (pol == ACL_COND_NONE) {
2413 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2414 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002417 }
2418
2419 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2420 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2421 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002424 }
Willy Tarreau88922352009-10-04 22:02:50 +02002425 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002426 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002427 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002428 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2429 }
2430 else {
2431 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002434 }
2435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436#ifdef TPROXY
2437 else if (!strcmp(args[0], "transparent")) {
2438 /* enable transparent proxy connections */
2439 curproxy->options |= PR_O_TRANSP;
2440 }
2441#endif
2442 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002443 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 if (*(args[1]) == 0) {
2447 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
2451 curproxy->maxconn = atol(args[1]);
2452 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002453 else if (!strcmp(args[0], "backlog")) { /* backlog */
2454 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002456
2457 if (*(args[1]) == 0) {
2458 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002461 }
2462 curproxy->backlog = atol(args[1]);
2463 }
Willy Tarreau86034312006-12-29 00:10:33 +01002464 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002465 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002467
Willy Tarreau86034312006-12-29 00:10:33 +01002468 if (*(args[1]) == 0) {
2469 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002472 }
2473 curproxy->fullconn = atol(args[1]);
2474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2476 if (*(args[1]) == 0) {
2477 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002481 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2482 if (err) {
2483 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2484 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002487 }
2488 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
2490 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2491 if (curproxy == &defproxy) {
2492 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002496 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 if (strchr(args[1], ':') == NULL) {
2500 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 }
2504 curproxy->dispatch_addr = *str2sa(args[1]);
2505 }
2506 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002507 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002508 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002509
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002510 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002511 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2512 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002517 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2519 err_code |= ERR_WARN;
2520
2521 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2522 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2523 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2524 }
2525 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2526 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2527 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2528 }
2529 else {
2530 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 else if (!strcmp(args[0], "server")) { /* server address */
2536 int cur_arg;
2537 char *rport;
2538 char *raddr;
2539 short realport;
2540 int do_check;
2541
2542 if (curproxy == &defproxy) {
2543 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549
2550 if (!*args[2]) {
2551 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002556
2557 err = invalid_char(args[1]);
2558 if (err) {
2559 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2560 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002563 }
2564
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2566 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_ABORT;
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
2571 /* the servers are linked backwards first */
2572 newsrv->next = curproxy->srv;
2573 curproxy->srv = newsrv;
2574 newsrv->proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002575 newsrv->conf.file = file;
2576 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577
2578 LIST_INIT(&newsrv->pendconns);
2579 do_check = 0;
2580 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002581 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 newsrv->id = strdup(args[1]);
2583
2584 /* several ways to check the port component :
2585 * - IP => port=+0, relative
2586 * - IP: => port=+0, relative
2587 * - IP:N => port=N, absolute
2588 * - IP:+N => port=+N, relative
2589 * - IP:-N => port=-N, relative
2590 */
2591 raddr = strdup(args[2]);
2592 rport = strchr(raddr, ':');
2593 if (rport) {
2594 *rport++ = 0;
2595 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002596 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 newsrv->state |= SRV_MAPPORTS;
2598 } else {
2599 realport = 0;
2600 newsrv->state |= SRV_MAPPORTS;
2601 }
2602
2603 newsrv->addr = *str2sa(raddr);
2604 newsrv->addr.sin_port = htons(realport);
2605 free(raddr);
2606
2607 newsrv->curfd = -1; /* no health-check in progress */
2608 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002609 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2610 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 newsrv->rise = DEF_RISETIME;
2612 newsrv->fall = DEF_FALLTIME;
2613 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau975c50b2009-10-10 19:34:06 +02002614 newsrv->uweight = newsrv->iweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002615 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002616 newsrv->slowstart = 0;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002617 newsrv->onerror = DEF_HANA_ONERR;
2618 newsrv->consecutive_errors_limit = DEF_HANA_ERRLIMIT;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002619
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 cur_arg = 3;
2621 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002622 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002623 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002624
2625 if (!*args[cur_arg + 1]) {
2626 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2627 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002630 }
2631
2632 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002633 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002634
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002635 if (newsrv->puid <= 0) {
2636 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002637 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002640 }
2641
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002642 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2643 if (node) {
2644 struct server *target = container_of(node, struct server, conf.id);
2645 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2646 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
2649 }
2650 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002651 cur_arg += 2;
2652 }
2653 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 newsrv->cookie = strdup(args[cur_arg + 1]);
2655 newsrv->cklen = strlen(args[cur_arg + 1]);
2656 cur_arg += 2;
2657 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002658 else if (!strcmp(args[cur_arg], "redir")) {
2659 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2660 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2661 cur_arg += 2;
2662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002664 if (!*args[cur_arg + 1]) {
2665 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2666 file, linenum, args[cur_arg]);
2667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
2669 }
2670
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002672 if (newsrv->rise <= 0) {
2673 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2674 file, linenum, args[cur_arg]);
2675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
2677 }
2678
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 newsrv->health = newsrv->rise;
2680 cur_arg += 2;
2681 }
2682 else if (!strcmp(args[cur_arg], "fall")) {
2683 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002684
2685 if (!*args[cur_arg + 1]) {
2686 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2687 file, linenum, args[cur_arg]);
2688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
2690 }
2691
2692 if (newsrv->fall <= 0) {
2693 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2694 file, linenum, args[cur_arg]);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 cur_arg += 2;
2700 }
2701 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002702 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2703 if (err) {
2704 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2705 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002708 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002709 if (val <= 0) {
2710 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2711 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002714 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002715 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 cur_arg += 2;
2717 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002718 else if (!strcmp(args[cur_arg], "fastinter")) {
2719 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2720 if (err) {
2721 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2722 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002725 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002726 if (val <= 0) {
2727 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2728 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002731 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002732 newsrv->fastinter = val;
2733 cur_arg += 2;
2734 }
2735 else if (!strcmp(args[cur_arg], "downinter")) {
2736 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2737 if (err) {
2738 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2739 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002742 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002743 if (val <= 0) {
2744 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2745 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002748 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002749 newsrv->downinter = val;
2750 cur_arg += 2;
2751 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002752 else if (!strcmp(args[cur_arg], "addr")) {
2753 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002754 cur_arg += 2;
2755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 else if (!strcmp(args[cur_arg], "port")) {
2757 newsrv->check_port = atol(args[cur_arg + 1]);
2758 cur_arg += 2;
2759 }
2760 else if (!strcmp(args[cur_arg], "backup")) {
2761 newsrv->state |= SRV_BACKUP;
2762 cur_arg ++;
2763 }
2764 else if (!strcmp(args[cur_arg], "weight")) {
2765 int w;
2766 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002767 if (w < 0 || w > 256) {
2768 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 file, linenum, newsrv->id, w);
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 Tarreau975c50b2009-10-10 19:34:06 +02002773 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 cur_arg += 2;
2775 }
2776 else if (!strcmp(args[cur_arg], "minconn")) {
2777 newsrv->minconn = atol(args[cur_arg + 1]);
2778 cur_arg += 2;
2779 }
2780 else if (!strcmp(args[cur_arg], "maxconn")) {
2781 newsrv->maxconn = atol(args[cur_arg + 1]);
2782 cur_arg += 2;
2783 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002784 else if (!strcmp(args[cur_arg], "maxqueue")) {
2785 newsrv->maxqueue = atol(args[cur_arg + 1]);
2786 cur_arg += 2;
2787 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002788 else if (!strcmp(args[cur_arg], "slowstart")) {
2789 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002790 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002791 if (err) {
2792 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2793 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002796 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002797 if (val <= 0) {
2798 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2799 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002802 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002803 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002804 cur_arg += 2;
2805 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002806 else if (!strcmp(args[cur_arg], "track")) {
2807
2808 if (!*args[cur_arg + 1]) {
2809 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2810 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002813 }
2814
2815 newsrv->trackit = strdup(args[cur_arg + 1]);
2816
2817 cur_arg += 2;
2818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 else if (!strcmp(args[cur_arg], "check")) {
2820 global.maxsock++;
2821 do_check = 1;
2822 cur_arg += 1;
2823 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002824 else if (!strcmp(args[cur_arg], "observe")) {
2825 if (!strcmp(args[cur_arg + 1], "none"))
2826 newsrv->observe = HANA_OBS_NONE;
2827 else if (!strcmp(args[cur_arg + 1], "layer4"))
2828 newsrv->observe = HANA_OBS_LAYER4;
2829 else if (!strcmp(args[cur_arg + 1], "layer7")) {
2830 if (curproxy->mode != PR_MODE_HTTP) {
2831 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
2832 file, linenum, args[cur_arg + 1]);
2833 err_code |= ERR_ALERT;
2834 }
2835 newsrv->observe = HANA_OBS_LAYER7;
2836 }
2837 else {
2838 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
2839 "'l4events', 'http-responses' but get '%s'\n",
2840 file, linenum, args[cur_arg], args[cur_arg + 1]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844
2845 cur_arg += 2;
2846 }
2847 else if (!strcmp(args[cur_arg], "on-error")) {
2848 if (!strcmp(args[cur_arg + 1], "fastinter"))
2849 newsrv->onerror = HANA_ONERR_FASTINTER;
2850 else if (!strcmp(args[cur_arg + 1], "fail-check"))
2851 newsrv->onerror = HANA_ONERR_FAILCHK;
2852 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
2853 newsrv->onerror = HANA_ONERR_SUDDTH;
2854 else if (!strcmp(args[cur_arg + 1], "mark-down"))
2855 newsrv->onerror = HANA_ONERR_MARKDWN;
2856 else {
2857 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
2858 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
2859 file, linenum, args[cur_arg], args[cur_arg + 1]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
2863
2864 cur_arg += 2;
2865 }
2866 else if (!strcmp(args[cur_arg], "error-limit")) {
2867 if (!*args[cur_arg + 1]) {
2868 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2869 file, linenum, args[cur_arg]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873
2874 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
2875
2876 if (newsrv->consecutive_errors_limit <= 0) {
2877 Alert("parsing [%s:%d]: %s has to be > 0.\n",
2878 file, linenum, args[cur_arg]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002884 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002886#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002887 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002888 file, linenum, "source", "usesrc");
2889#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002890 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002892#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
2896 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002897 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2898
2899 if (port_low != port_high) {
2900 int i;
2901 if (port_low <= 0 || port_low > 65535 ||
2902 port_high <= 0 || port_high > 65535 ||
2903 port_low > port_high) {
2904 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2905 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002908 }
2909 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2910 for (i = 0; i < newsrv->sport_range->size; i++)
2911 newsrv->sport_range->ports[i] = port_low + i;
2912 }
2913
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002915 while (*(args[cur_arg])) {
2916 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002917#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2918#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002919 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2920 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2921 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002924 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002925#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002926 if (!*args[cur_arg + 1]) {
2927 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2928 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002931 }
2932 if (!strcmp(args[cur_arg + 1], "client")) {
2933 newsrv->state |= SRV_TPROXY_CLI;
2934 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2935 newsrv->state |= SRV_TPROXY_CIP;
2936 } else {
2937 newsrv->state |= SRV_TPROXY_ADDR;
2938 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2939 }
2940 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002941#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002942 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002943#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002944 cur_arg += 2;
2945 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002946#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002947 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002948 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002951#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2952 } /* "usesrc" */
2953
2954 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2955#ifdef SO_BINDTODEVICE
2956 if (!*args[cur_arg + 1]) {
2957 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2958 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002961 }
2962 if (newsrv->iface_name)
2963 free(newsrv->iface_name);
2964
2965 newsrv->iface_name = strdup(args[cur_arg + 1]);
2966 newsrv->iface_len = strlen(newsrv->iface_name);
2967 global.last_checks |= LSTCHK_NETADM;
2968#else
2969 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2970 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002973#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002974 cur_arg += 2;
2975 continue;
2976 }
2977 /* this keyword in not an option of "source" */
2978 break;
2979 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002981 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2982 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2983 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002988 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 }
2993 }
2994
2995 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002996 if (newsrv->trackit) {
2997 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2998 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003001 }
3002
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003003 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3004 newsrv->check_port = newsrv->check_addr.sin_port;
3005
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3007 newsrv->check_port = realport; /* by default */
3008 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003009 /* not yet valid, because no port was set on
3010 * the server either. We'll check if we have
3011 * a known port on the first listener.
3012 */
3013 struct listener *l;
3014 l = curproxy->listen;
3015 if (l) {
3016 int port;
3017 port = (l->addr.ss_family == AF_INET6)
3018 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3019 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3020 newsrv->check_port = port;
3021 }
3022 }
3023 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3025 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003029
3030 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 newsrv->state |= SRV_CHECKED;
3032 }
3033
3034 if (newsrv->state & SRV_BACKUP)
3035 curproxy->srv_bck++;
3036 else
3037 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003038
3039 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
3041 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003042 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 int facility;
3044
3045 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3046 curproxy->logfac1 = global.logfac1;
3047 curproxy->logsrv1 = global.logsrv1;
3048 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003049 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 curproxy->logfac2 = global.logfac2;
3051 curproxy->logsrv2 = global.logsrv2;
3052 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003053 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
3055 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003056 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057
3058 facility = get_log_facility(args[2]);
3059 if (facility < 0) {
3060 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3061 exit(1);
3062 }
3063
3064 level = 7; /* max syslog level = debug */
3065 if (*(args[3])) {
3066 level = get_log_level(args[3]);
3067 if (level < 0) {
3068 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3069 exit(1);
3070 }
3071 }
3072
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003073 minlvl = 0; /* limit syslog level to this level (emerg) */
3074 if (*(args[4])) {
3075 minlvl = get_log_level(args[4]);
3076 if (level < 0) {
3077 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3078 exit(1);
3079 }
3080 }
3081
Robert Tsai81ae1952007-12-05 10:47:29 +01003082 if (args[1][0] == '/') {
3083 logsrv.u.addr.sa_family = AF_UNIX;
3084 logsrv.u.un = *str2sun(args[1]);
3085 } else {
3086 logsrv.u.addr.sa_family = AF_INET;
3087 logsrv.u.in = *str2sa(args[1]);
3088 if (!logsrv.u.in.sin_port) {
3089 logsrv.u.in.sin_port =
3090 htons(SYSLOG_PORT);
3091 }
3092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093
3094 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003095 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 curproxy->logfac1 = facility;
3097 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003098 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 }
3100 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003101 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 curproxy->logfac2 = facility;
3103 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003104 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 }
3106 else {
3107 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 }
3111 }
3112 else {
3113 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3114 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
3118 }
3119 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003120 int cur_arg;
3121
Willy Tarreau977b8e42006-12-29 14:19:17 +01003122 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003124
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003126 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3127 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003131
3132 /* we must first clear any optional default setting */
3133 curproxy->options &= ~PR_O_TPXY_MASK;
3134 free(curproxy->iface_name);
3135 curproxy->iface_name = NULL;
3136 curproxy->iface_len = 0;
3137
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 curproxy->source_addr = *str2sa(args[1]);
3139 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003140
3141 cur_arg = 2;
3142 while (*(args[cur_arg])) {
3143 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003144#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3145#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003146 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3147 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3148 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003151 }
3152#endif
3153 if (!*args[cur_arg + 1]) {
3154 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3155 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003158 }
3159
3160 if (!strcmp(args[cur_arg + 1], "client")) {
3161 curproxy->options |= PR_O_TPXY_CLI;
3162 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3163 curproxy->options |= PR_O_TPXY_CIP;
3164 } else {
3165 curproxy->options |= PR_O_TPXY_ADDR;
3166 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3167 }
3168 global.last_checks |= LSTCHK_NETADM;
3169#if !defined(CONFIG_HAP_LINUX_TPROXY)
3170 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003171#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003172#else /* no TPROXY support */
3173 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003174 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003177#endif
3178 cur_arg += 2;
3179 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003180 }
3181
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003182 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3183#ifdef SO_BINDTODEVICE
3184 if (!*args[cur_arg + 1]) {
3185 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003189 }
3190 if (curproxy->iface_name)
3191 free(curproxy->iface_name);
3192
3193 curproxy->iface_name = strdup(args[cur_arg + 1]);
3194 curproxy->iface_len = strlen(curproxy->iface_name);
3195 global.last_checks |= LSTCHK_NETADM;
3196#else
3197 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3198 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003201#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003202 cur_arg += 2;
3203 continue;
3204 }
3205 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3206 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003211 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3212 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3213 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3218 regex_t *preg;
3219 if (curproxy == &defproxy) {
3220 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003224 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003226
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 if (*(args[1]) == 0 || *(args[2]) == 0) {
3228 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3229 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
3233
3234 preg = calloc(1, sizeof(regex_t));
3235 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3236 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 }
3240
3241 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3242 if (err) {
3243 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3244 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003247 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 }
3249 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3250 regex_t *preg;
3251 if (curproxy == &defproxy) {
3252 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003256 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003258
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 if (*(args[1]) == 0) {
3260 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
3264
3265 preg = calloc(1, sizeof(regex_t));
3266 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3267 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 }
3271
3272 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003273 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 }
3275 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3276 regex_t *preg;
3277 if (curproxy == &defproxy) {
3278 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003282 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003284
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 if (*(args[1]) == 0) {
3286 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
3290
3291 preg = calloc(1, sizeof(regex_t));
3292 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3293 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
3297
3298 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003299 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3302 regex_t *preg;
3303 if (curproxy == &defproxy) {
3304 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003308 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003310
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 if (*(args[1]) == 0) {
3312 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }
3316
3317 preg = calloc(1, sizeof(regex_t));
3318 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3319 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
3323
3324 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003325 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
3327 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3328 regex_t *preg;
3329 if (curproxy == &defproxy) {
3330 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003334 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003336
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 if (*(args[1]) == 0) {
3338 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 }
3342
3343 preg = calloc(1, sizeof(regex_t));
3344 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3345 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
3349
3350 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003351 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003353 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3354 regex_t *preg;
3355 if (curproxy == &defproxy) {
3356 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003359 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003360 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003362
Willy Tarreaub8750a82006-09-03 09:56:00 +02003363 if (*(args[1]) == 0) {
3364 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003367 }
3368
3369 preg = calloc(1, sizeof(regex_t));
3370 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3371 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003374 }
3375
3376 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003377 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003378 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003379 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3380 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003381 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003385 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003386 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003388
Willy Tarreau977b8e42006-12-29 14:19:17 +01003389 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003390 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3391 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003394 }
3395
3396 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003397 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003398 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003401 }
3402
3403 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003404 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003405 }
3406 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3407 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003408 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003409 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003412 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003413 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003414 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003415
Willy Tarreau977b8e42006-12-29 14:19:17 +01003416 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003417 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003421 }
3422
3423 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003424 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003425 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003428 }
3429
3430 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003431 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3434 regex_t *preg;
3435 if (curproxy == &defproxy) {
3436 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003440 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003442
Willy Tarreaubaaee002006-06-26 02:48:02 +02003443 if (*(args[1]) == 0 || *(args[2]) == 0) {
3444 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 }
3449
3450 preg = calloc(1, sizeof(regex_t));
3451 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3452 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }
3456
3457 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3458 if (err) {
3459 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3460 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003463 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003464 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 }
3466 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3467 regex_t *preg;
3468 if (curproxy == &defproxy) {
3469 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003473 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003475
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 if (*(args[1]) == 0) {
3477 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 }
3481
3482 preg = calloc(1, sizeof(regex_t));
3483 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3484 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 }
3488
3489 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003490 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 }
3492 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3493 regex_t *preg;
3494 if (curproxy == &defproxy) {
3495 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003499 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003501
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 if (*(args[1]) == 0) {
3503 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 }
3507
3508 preg = calloc(1, sizeof(regex_t));
3509 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3510 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 }
3514
3515 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003516 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 }
3518 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3519 regex_t *preg;
3520 if (curproxy == &defproxy) {
3521 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003525 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003527
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 if (*(args[1]) == 0) {
3529 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
3533
3534 preg = calloc(1, sizeof(regex_t));
3535 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3536 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }
3540
3541 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003542 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
3544 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3545 regex_t *preg;
3546 if (curproxy == &defproxy) {
3547 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003551 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003553
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 if (*(args[1]) == 0) {
3555 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
3559
3560 preg = calloc(1, sizeof(regex_t));
3561 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3562 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
3566
3567 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003568 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003570 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3571 regex_t *preg;
3572 if (curproxy == &defproxy) {
3573 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003576 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003577 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003579
Willy Tarreaub8750a82006-09-03 09:56:00 +02003580 if (*(args[1]) == 0) {
3581 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003584 }
3585
3586 preg = calloc(1, sizeof(regex_t));
3587 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3588 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003591 }
3592
3593 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003594 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003597 struct wordlist *wl;
3598
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 if (curproxy == &defproxy) {
3600 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003604 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 if (*(args[1]) == 0) {
3608 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_ALERT | ERR_FATAL;
3610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003612
3613 wl = calloc(1, sizeof(*wl));
3614 wl->s = strdup(args[1]);
3615 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003616 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
3618 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3619 regex_t *preg;
3620
3621 if (*(args[1]) == 0 || *(args[2]) == 0) {
3622 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003627 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003629
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 preg = calloc(1, sizeof(regex_t));
3631 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3632 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 }
3636
3637 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3638 if (err) {
3639 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3640 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003644 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 }
3646 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3647 regex_t *preg;
3648 if (curproxy == &defproxy) {
3649 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003653 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003655
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 if (*(args[1]) == 0) {
3657 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 }
3661
3662 preg = calloc(1, sizeof(regex_t));
3663 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3664 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 }
3668
3669 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3670 if (err) {
3671 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3672 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 }
3676 }
3677 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3678 regex_t *preg;
3679 if (curproxy == &defproxy) {
3680 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003684 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003686
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 if (*(args[1]) == 0) {
3688 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 }
3692
3693 preg = calloc(1, sizeof(regex_t));
3694 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3695 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 }
3699
3700 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3701 if (err) {
3702 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3703 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 }
3707 }
3708 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3709 regex_t *preg;
3710 if (curproxy == &defproxy) {
3711 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003715 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717
3718 if (*(args[1]) == 0 || *(args[2]) == 0) {
3719 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3720 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
3724
3725 preg = calloc(1, sizeof(regex_t));
3726 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3727 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 }
3731
3732 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3733 if (err) {
3734 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3735 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 }
3739 }
3740 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3741 regex_t *preg;
3742 if (curproxy == &defproxy) {
3743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003747 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003749
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 if (*(args[1]) == 0) {
3751 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 }
3755
3756 preg = calloc(1, sizeof(regex_t));
3757 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3758 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 }
3762
3763 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3764 if (err) {
3765 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3766 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 }
3770 }
3771 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3772 regex_t *preg;
3773 if (curproxy == &defproxy) {
3774 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003778 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003780
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 if (*(args[1]) == 0) {
3782 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 }
3786
3787 preg = calloc(1, sizeof(regex_t));
3788 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3789 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 }
3793
3794 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3795 if (err) {
3796 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3797 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
3801 }
3802 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003803 struct wordlist *wl;
3804
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 if (curproxy == &defproxy) {
3806 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003810 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 if (*(args[1]) == 0) {
3814 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003819 wl = calloc(1, sizeof(*wl));
3820 wl->s = strdup(args[1]);
3821 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
3823 else if (!strcmp(args[0], "errorloc") ||
3824 !strcmp(args[0], "errorloc302") ||
3825 !strcmp(args[0], "errorloc303")) { /* error location */
3826 int errnum, errlen;
3827 char *err;
3828
Willy Tarreau977b8e42006-12-29 14:19:17 +01003829 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003831
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003833 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 }
3837
3838 errnum = atol(args[1]);
3839 if (!strcmp(args[0], "errorloc303")) {
3840 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3841 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3842 } else {
3843 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3844 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3845 }
3846
Willy Tarreau0f772532006-12-23 20:51:41 +01003847 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3848 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003849 chunk_destroy(&curproxy->errmsg[rc]);
3850 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003851 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003854
3855 if (rc >= HTTP_ERR_SIZE) {
3856 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3857 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 free(err);
3859 }
3860 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003861 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3862 int errnum, errlen, fd;
3863 char *err;
3864 struct stat stat;
3865
3866 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003868
3869 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003870 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003873 }
3874
3875 fd = open(args[2], O_RDONLY);
3876 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3877 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3878 file, linenum, args[2], args[1]);
3879 if (fd >= 0)
3880 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003883 }
3884
Willy Tarreau27a674e2009-08-17 07:23:33 +02003885 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003886 errlen = stat.st_size;
3887 } else {
3888 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003889 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003891 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003892 }
3893
3894 err = malloc(errlen); /* malloc() must succeed during parsing */
3895 errnum = read(fd, err, errlen);
3896 if (errnum != errlen) {
3897 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3898 file, linenum, args[2], args[1]);
3899 close(fd);
3900 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003903 }
3904 close(fd);
3905
3906 errnum = atol(args[1]);
3907 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3908 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003909 chunk_destroy(&curproxy->errmsg[rc]);
3910 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003911 break;
3912 }
3913 }
3914
3915 if (rc >= HTTP_ERR_SIZE) {
3916 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3917 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003919 free(err);
3920 }
3921 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003923 struct cfg_kw_list *kwl;
3924 int index;
3925
3926 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3927 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3928 if (kwl->kw[index].section != CFG_LISTEN)
3929 continue;
3930 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3931 /* prepare error message just in case */
3932 snprintf(trash, sizeof(trash),
3933 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003934 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3935 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003936 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003939 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003940 else if (rc > 0) {
3941 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_WARN;
3943 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003944 }
Willy Tarreau93893792009-07-23 13:19:11 +02003945 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003946 }
3947 }
3948 }
3949
Willy Tarreau6daf3432008-01-22 16:44:08 +01003950 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 }
Willy Tarreau93893792009-07-23 13:19:11 +02003954 out:
3955 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956}
3957
3958
3959/*
3960 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003961 * Returns the error code, 0 if OK, or any combination of :
3962 * - ERR_ABORT: must abort ASAP
3963 * - ERR_FATAL: we can continue parsing but not start the service
3964 * - ERR_WARN: a warning has been emitted
3965 * - ERR_ALERT: an alert has been emitted
3966 * Only the two first ones can stop processing, the two others are just
3967 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003969int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003971 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 FILE *f;
3973 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003974 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003975 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 if ((f=fopen(file,"r")) == NULL)
3978 return -1;
3979
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003980 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003981 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003982 char *end;
3983 char *args[MAX_LINE_ARGS + 1];
3984 char *line = thisline;
3985
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 linenum++;
3987
3988 end = line + strlen(line);
3989
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003990 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3991 /* Check if we reached the limit and the last char is not \n.
3992 * Watch out for the last line without the terminating '\n'!
3993 */
3994 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003995 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003997 }
3998
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004000 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 line++;
4002
4003 arg = 0;
4004 args[arg] = line;
4005
4006 while (*line && arg < MAX_LINE_ARGS) {
4007 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4008 * C equivalent value. Other combinations left unchanged (eg: \1).
4009 */
4010 if (*line == '\\') {
4011 int skip = 0;
4012 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4013 *line = line[1];
4014 skip = 1;
4015 }
4016 else if (line[1] == 'r') {
4017 *line = '\r';
4018 skip = 1;
4019 }
4020 else if (line[1] == 'n') {
4021 *line = '\n';
4022 skip = 1;
4023 }
4024 else if (line[1] == 't') {
4025 *line = '\t';
4026 skip = 1;
4027 }
4028 else if (line[1] == 'x') {
4029 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
4030 unsigned char hex1, hex2;
4031 hex1 = toupper(line[2]) - '0';
4032 hex2 = toupper(line[3]) - '0';
4033 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4034 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4035 *line = (hex1<<4) + hex2;
4036 skip = 3;
4037 }
4038 else {
4039 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004040 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
4042 }
4043 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004044 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 end -= skip;
4046 }
4047 line++;
4048 }
4049 else if (*line == '#' || *line == '\n' || *line == '\r') {
4050 /* end of string, end of loop */
4051 *line = 0;
4052 break;
4053 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004054 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004056 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004057 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 line++;
4059 args[++arg] = line;
4060 }
4061 else {
4062 line++;
4063 }
4064 }
4065
4066 /* empty line */
4067 if (!**args)
4068 continue;
4069
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004070 if (*line) {
4071 /* we had to stop due to too many args.
4072 * Let's terminate the string, print the offending part then cut the
4073 * last arg.
4074 */
4075 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4076 line++;
4077 *line = '\0';
4078
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004079 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004080 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004081 err_code |= ERR_ALERT | ERR_FATAL;
4082 args[arg] = line;
4083 }
4084
Willy Tarreau540abe42007-05-02 20:50:16 +02004085 /* zero out remaining args and ensure that at least one entry
4086 * is zeroed out.
4087 */
4088 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089 args[arg] = line;
4090 }
4091
Willy Tarreau3842f002009-06-14 11:39:52 +02004092 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004093 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004094 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004095 for (arg=0; *args[arg+1]; arg++)
4096 args[arg] = args[arg+1]; // shift args after inversion
4097 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004098 else if (!strcmp(args[0], "default")) {
4099 kwm = KWM_DEF;
4100 for (arg=0; *args[arg+1]; arg++)
4101 args[arg] = args[arg+1]; // shift args after inversion
4102 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004103
Willy Tarreau3842f002009-06-14 11:39:52 +02004104 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4105 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004107 }
4108
Willy Tarreau977b8e42006-12-29 14:19:17 +01004109 if (!strcmp(args[0], "listen") ||
4110 !strcmp(args[0], "frontend") ||
4111 !strcmp(args[0], "backend") ||
4112 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004113 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004115 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004116 cursection = strdup(args[0]);
4117 }
4118 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004120 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004121 cursection = strdup(args[0]);
4122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004123 /* else it's a section keyword */
4124
4125 switch (confsect) {
4126 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 break;
4129 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004130 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 break;
4132 default:
4133 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004135 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004136
4137 if (err_code & ERR_ABORT)
4138 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004140 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004141 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004143 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004144}
4145
Willy Tarreaubb925012009-07-23 13:36:36 +02004146/*
4147 * Returns the error code, 0 if OK, or any combination of :
4148 * - ERR_ABORT: must abort ASAP
4149 * - ERR_FATAL: we can continue parsing but not start the service
4150 * - ERR_WARN: a warning has been emitted
4151 * - ERR_ALERT: an alert has been emitted
4152 * Only the two first ones can stop processing, the two others are just
4153 * indicators.
4154 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004155int check_config_validity()
4156{
4157 int cfgerr = 0;
4158 struct proxy *curproxy = NULL;
4159 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004160 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004161 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162
4163 /*
4164 * Now, check for the integrity of all that we have collected.
4165 */
4166
4167 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004168 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004170 /* first, we will invert the proxy list order */
4171 curproxy = NULL;
4172 while (proxy) {
4173 struct proxy *next;
4174
4175 next = proxy->next;
4176 proxy->next = curproxy;
4177 curproxy = proxy;
4178 if (!next)
4179 break;
4180 proxy = next;
4181 }
4182
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004184 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 }
4188
4189 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004190 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004191 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004192 unsigned int next_id;
4193
4194 if (!curproxy->uuid) {
4195 /* proxy ID not set, use automatic numbering with first
4196 * spare entry starting with next_pxid.
4197 */
4198 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4199 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4200 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4201 next_pxid++;
4202 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004203
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004205 /* ensure we don't keep listeners uselessly bound */
4206 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004207 curproxy = curproxy->next;
4208 continue;
4209 }
4210
Willy Tarreauff01a212009-03-15 13:46:16 +01004211 switch (curproxy->mode) {
4212 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004213 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004214 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004215 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4216 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004217 cfgerr++;
4218 }
4219
4220 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004221 Warning("config : servers will be ignored for %s '%s'.\n",
4222 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004223 break;
4224
4225 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004226 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004227 break;
4228
4229 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004230 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004231 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004232 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4233 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004234 cfgerr++;
4235 }
4236 break;
4237 }
4238
4239 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004240 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4241 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 cfgerr++;
4243 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004244
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004245 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004246 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004247 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004248 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4249 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004250 cfgerr++;
4251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004253 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004254 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4255 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004256 cfgerr++;
4257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004259 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004260 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4261 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004262 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004263 }
4264 }
4265 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4266 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4267 /* If no LB algo is set in a backend, and we're not in
4268 * transparent mode, dispatch mode nor proxy mode, we
4269 * want to use balance roundrobin by default.
4270 */
4271 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4272 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 }
4274 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004275
Willy Tarreau82936582007-11-30 15:20:09 +01004276 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4277 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004278 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4279 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004280 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004281 }
4282
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004283 /* if a default backend was specified, let's find it */
4284 if (curproxy->defbe.name) {
4285 struct proxy *target;
4286
Alex Williams96532db2009-11-01 21:27:13 -05004287 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004288 if (!target) {
4289 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4290 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004291 cfgerr++;
4292 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004293 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4294 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004295 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004296 } else {
4297 free(curproxy->defbe.name);
4298 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004299 /* we force the backend to be present on at least all of
4300 * the frontend's processes.
4301 */
4302 target->bind_proc = curproxy->bind_proc ?
4303 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 }
4305 }
4306
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004307 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004308 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4309 /* map jump target for ACT_SETBE in req_rep chain */
4310 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004311 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004312 struct proxy *target;
4313
Willy Tarreaua496b602006-12-17 23:15:24 +01004314 if (exp->action != ACT_SETBE)
4315 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004316
Alex Williams96532db2009-11-01 21:27:13 -05004317 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004318 if (!target) {
4319 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4320 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004321 cfgerr++;
4322 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004323 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4324 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004325 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004326 } else {
4327 free((void *)exp->replace);
4328 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004329 /* we force the backend to be present on at least all of
4330 * the frontend's processes.
4331 */
4332 target->bind_proc = curproxy->bind_proc ?
4333 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004334 }
4335 }
4336 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004337
4338 /* find the target proxy for 'use_backend' rules */
4339 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004340 struct proxy *target;
4341
Alex Williams96532db2009-11-01 21:27:13 -05004342 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004343
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004344 if (!target) {
4345 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4346 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004347 cfgerr++;
4348 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004349 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4350 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004351 cfgerr++;
4352 } else {
4353 free((void *)rule->be.name);
4354 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004355 /* we force the backend to be present on at least all of
4356 * the frontend's processes.
4357 */
4358 target->bind_proc = curproxy->bind_proc ?
4359 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004360 }
4361 }
4362
Willy Tarreau2738a142006-07-08 17:28:09 +02004363 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004364 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004365 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004366 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004367 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004368 " | While not properly invalid, you will certainly encounter various problems\n"
4369 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004370 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004371 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004372 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004373 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004374
Willy Tarreau1fa31262007-12-03 00:36:16 +01004375 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4376 * We must still support older configurations, so let's find out whether those
4377 * parameters have been set or must be copied from contimeouts.
4378 */
4379 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004380 if (!curproxy->timeout.tarpit ||
4381 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004382 /* tarpit timeout not set. We search in the following order:
4383 * default.tarpit, curr.connect, default.connect.
4384 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004385 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004386 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004387 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004388 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004389 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004390 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004391 }
4392 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004393 (!curproxy->timeout.queue ||
4394 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004395 /* queue timeout not set. We search in the following order:
4396 * default.queue, curr.connect, default.connect.
4397 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004398 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004399 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004400 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004401 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004402 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004403 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004404 }
4405 }
4406
Willy Tarreauf3c69202006-07-09 16:42:34 +02004407 if (curproxy->options & PR_O_SSL3_CHK) {
4408 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4409 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4410 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4411 }
4412
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004413 /* The small pools required for the capture lists */
4414 if (curproxy->nb_req_cap)
4415 curproxy->req_cap_pool = create_pool("ptrcap",
4416 curproxy->nb_req_cap * sizeof(char *),
4417 MEM_F_SHARED);
4418 if (curproxy->nb_rsp_cap)
4419 curproxy->rsp_cap_pool = create_pool("ptrcap",
4420 curproxy->nb_rsp_cap * sizeof(char *),
4421 MEM_F_SHARED);
4422
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004423 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4424 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4425 MEM_F_SHARED);
4426
Willy Tarreau86034312006-12-29 00:10:33 +01004427 /* for backwards compatibility with "listen" instances, if
4428 * fullconn is not set but maxconn is set, then maxconn
4429 * is used.
4430 */
4431 if (!curproxy->fullconn)
4432 curproxy->fullconn = curproxy->maxconn;
4433
Willy Tarreaubaaee002006-06-26 02:48:02 +02004434 /* first, we will invert the servers list order */
4435 newsrv = NULL;
4436 while (curproxy->srv) {
4437 struct server *next;
4438
4439 next = curproxy->srv->next;
4440 curproxy->srv->next = newsrv;
4441 newsrv = curproxy->srv;
4442 if (!next)
4443 break;
4444 curproxy->srv = next;
4445 }
4446
Willy Tarreau20697042007-11-15 23:26:18 +01004447 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004448 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004450 /* We have to initialize the server lookup mechanism depending
4451 * on what LB algorithm was choosen.
4452 */
4453
4454 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4455 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4456 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004457 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4458 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4459 init_server_map(curproxy);
4460 } else {
4461 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4462 fwrr_init_server_groups(curproxy);
4463 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004464 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004465
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004466 case BE_LB_KIND_LC:
4467 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004468 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004469 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004470
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004471 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004472 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4473 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4474 chash_init_server_tree(curproxy);
4475 } else {
4476 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4477 init_server_map(curproxy);
4478 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004479 break;
4480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481
4482 if (curproxy->options & PR_O_LOGASAP)
4483 curproxy->to_log &= ~LW_BYTES;
4484
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004485 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4486 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4487 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4488 proxy_type_str(curproxy), curproxy->id);
4489 err_code |= ERR_WARN;
4490 }
4491
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004493 * ensure that we're not cross-dressing a TCP server into HTTP.
4494 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004495 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004496 newsrv = curproxy->srv;
4497 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004498 if (!newsrv->puid) {
4499 /* server ID not set, use automatic numbering with first
4500 * spare entry starting with next_svid.
4501 */
4502 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4503 newsrv->conf.id.key = newsrv->puid = next_id;
4504 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4505 next_id++;
4506 }
4507
Willy Tarreau21d2af32008-02-14 20:25:24 +01004508 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004509 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4510 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004511 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004512 }
4513 newsrv = newsrv->next;
4514 }
4515
4516 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 * If this server supports a maxconn parameter, it needs a dedicated
4518 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004519 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 */
4521 newsrv = curproxy->srv;
4522 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004523 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524 /* Only 'minconn' was specified, or it was higher than or equal
4525 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4526 * this will avoid further useless expensive computations.
4527 */
4528 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004529 } else if (newsrv->maxconn && !newsrv->minconn) {
4530 /* minconn was not specified, so we set it to maxconn */
4531 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004532 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004533 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4534 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004535 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 }
4537
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004538 if (newsrv->trackit) {
4539 struct proxy *px;
4540 struct server *srv;
4541 char *pname, *sname;
4542
4543 pname = newsrv->trackit;
4544 sname = strrchr(pname, '/');
4545
4546 if (sname)
4547 *sname++ = '\0';
4548 else {
4549 sname = pname;
4550 pname = NULL;
4551 }
4552
4553 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004554 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004555 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004556 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4557 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004558 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004559 cfgerr++;
4560 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004561 }
4562 } else
4563 px = curproxy;
4564
4565 srv = findserver(px, sname);
4566 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004567 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4568 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004569 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004570 cfgerr++;
4571 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004572 }
4573
4574 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004575 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004576 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004577 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004578 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004579 cfgerr++;
4580 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004581 }
4582
4583 if (curproxy != px &&
4584 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004585 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004586 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004587 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004588 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004589 cfgerr++;
4590 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004591 }
4592
4593 newsrv->tracked = srv;
4594 newsrv->tracknext = srv->tracknext;
4595 srv->tracknext = newsrv;
4596
4597 free(newsrv->trackit);
4598 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004599 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 newsrv = newsrv->next;
4601 }
4602
Willy Tarreauc1a21672009-08-16 22:37:44 +02004603 if (curproxy->cap & PR_CAP_FE) {
4604 if (curproxy->tcp_req.inspect_delay ||
4605 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4606 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4607
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004608 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004609 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004610 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004611 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004612
4613 /* both TCP and HTTP must check switching rules */
4614 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4615 }
4616
4617 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004618 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004619 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004620 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004621 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004622
4623 /* If the backend does requires RDP cookie persistence, we have to
4624 * enable the corresponding analyser.
4625 */
4626 if (curproxy->options2 & PR_O2_RDPC_PRST)
4627 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4628 }
4629
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004630 listener = NULL;
4631 while (curproxy->listen) {
4632 struct listener *next;
4633
4634 next = curproxy->listen->next;
4635 curproxy->listen->next = listener;
4636 listener = curproxy->listen;
4637
4638 if (!next)
4639 break;
4640
4641 curproxy->listen = next;
4642 }
4643
Willy Tarreaue6b98942007-10-29 01:09:36 +01004644 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004645 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004646 listener = curproxy->listen;
4647 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004648 if (!listener->luid) {
4649 /* listener ID not set, use automatic numbering with first
4650 * spare entry starting with next_luid.
4651 */
4652 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4653 listener->conf.id.key = listener->luid = next_id;
4654 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4655 next_id++;
4656 }
4657
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004658 /* enable separate counters */
4659 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4660 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4661 if (!listener->name) {
4662 sprintf(trash, "sock-%d", listener->luid);
4663 listener->name = strdup(trash);
4664 }
4665 }
4666
Willy Tarreaue6b98942007-10-29 01:09:36 +01004667 if (curproxy->options & PR_O_TCP_NOLING)
4668 listener->options |= LI_O_NOLINGER;
4669 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004670 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004671 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004672 listener->accept = event_accept;
4673 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004674 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004675 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004676
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004677 /* smart accept mode is automatic in HTTP mode */
4678 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4679 (curproxy->mode == PR_MODE_HTTP &&
4680 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4681 listener->options |= LI_O_NOQUICKACK;
4682
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004683 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004684 listener = listener->next;
4685 }
4686
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 curproxy = curproxy->next;
4688 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004689
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004690 /*
4691 * Recount currently required checks.
4692 */
4693
4694 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4695 int optnum;
4696
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004697 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4698 if (curproxy->options & cfg_opts[optnum].val)
4699 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004700
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004701 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4702 if (curproxy->options2 & cfg_opts2[optnum].val)
4703 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004704 }
4705
Willy Tarreaubb925012009-07-23 13:36:36 +02004706 if (cfgerr > 0)
4707 err_code |= ERR_ALERT | ERR_FATAL;
4708 out:
4709 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710}
4711
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004712/*
4713 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4714 * parsing sessions.
4715 */
4716void cfg_register_keywords(struct cfg_kw_list *kwl)
4717{
4718 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4719}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004721/*
4722 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4723 */
4724void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4725{
4726 LIST_DEL(&kwl->list);
4727 LIST_INIT(&kwl->list);
4728}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729
4730/*
4731 * Local variables:
4732 * c-indent-level: 8
4733 * c-basic-offset: 8
4734 * End:
4735 */