blob: 34d4476e2edd435f8aeb6410609c461284662153 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004 * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020043#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020045#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020046#include <proto/lb_fwlc.h>
47#include <proto/lb_fwrr.h>
48#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020050#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010051#include <proto/protocols.h>
52#include <proto/proto_tcp.h>
53#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010054#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010056#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/task.h>
58
59
Willy Tarreauf3c69202006-07-09 16:42:34 +020060/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
61 * ssl-hello-chk option to ensure that the remote server speaks SSL.
62 *
63 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
64 */
65const char sslv3_client_hello_pkt[] = {
66 "\x16" /* ContentType : 0x16 = Hanshake */
67 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
68 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
69 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
70 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
71 "\x03\x00" /* Hello Version : 0x0300 = v3 */
72 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
73 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
74 "\x00" /* Session ID length : empty (no session ID) */
75 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
76 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
77 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
78 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
79 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
80 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
81 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
82 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
83 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
84 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
85 "\x00\x38" "\x00\x39" "\x00\x3A"
86 "\x01" /* Compression Length : 0x01 = 1 byte for types */
87 "\x00" /* Compression Type : 0x00 = NULL compression */
88};
89
Willy Tarreau3842f002009-06-14 11:39:52 +020090/* various keyword modifiers */
91enum kw_mod {
92 KWM_STD = 0, /* normal */
93 KWM_NO, /* "no" prefixed before the keyword */
94 KWM_DEF, /* "default" prefixed before the keyword */
95};
96
Willy Tarreau13943ab2006-12-31 00:24:10 +010097/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010098struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010099 const char *name;
100 unsigned int val;
101 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100102 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100103};
104
105/* proxy->options */
106static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
113 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
114 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
115 { "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 },
118 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
119 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100120 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100121 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
122 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100123#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100124 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100125#endif
126
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100127 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100128};
129
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100130/* proxy->options2 */
131static const struct cfg_opt cfg_opts2[] =
132{
133#ifdef CONFIG_HAP_LINUX_SPLICE
134 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
135 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
136 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
137#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200138 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
139 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200140 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
141 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200142 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200143 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200144 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200145 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200146 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100147 { NULL, 0, 0, 0 }
148};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200149
Willy Tarreau6daf3432008-01-22 16:44:08 +0100150static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200151static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
152int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100153int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200155/* List head of all known configuration keywords */
156static struct cfg_kw_list cfg_keywords = {
157 .list = LIST_HEAD_INIT(cfg_keywords.list)
158};
159
Willy Tarreaubaaee002006-06-26 02:48:02 +0200160/*
161 * converts <str> to a list of listeners which are dynamically allocated.
162 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
163 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
164 * - <port> is a numerical port from 1 to 65535 ;
165 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
166 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200167 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200169static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170{
171 struct listener *l;
172 char *c, *next, *range, *dupstr;
173 int port, end;
174
175 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177 while (next && *next) {
178 struct sockaddr_storage ss;
179
180 str = next;
181 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100182 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183 *next++ = 0;
184 }
185
186 /* 2) look for the addr/port delimiter, it's the last colon. */
187 if ((range = strrchr(str, ':')) == NULL) {
188 Alert("Missing port number: '%s'\n", str);
189 goto fail;
190 }
191
192 *range++ = 0;
193
194 if (strrchr(str, ':') != NULL) {
195 /* IPv6 address contains ':' */
196 memset(&ss, 0, sizeof(ss));
197 ss.ss_family = AF_INET6;
198
199 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
200 Alert("Invalid server address: '%s'\n", str);
201 goto fail;
202 }
203 }
204 else {
205 memset(&ss, 0, sizeof(ss));
206 ss.ss_family = AF_INET;
207
208 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
209 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
210 }
211 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
212 struct hostent *he;
213
214 if ((he = gethostbyname(str)) == NULL) {
215 Alert("Invalid server name: '%s'\n", str);
216 goto fail;
217 }
218 else
219 ((struct sockaddr_in *)&ss)->sin_addr =
220 *(struct in_addr *) *(he->h_addr_list);
221 }
222 }
223
224 /* 3) look for the port-end delimiter */
225 if ((c = strchr(range, '-')) != NULL) {
226 *c++ = 0;
227 end = atol(c);
228 }
229 else {
230 end = atol(range);
231 }
232
233 port = atol(range);
234
235 if (port < 1 || port > 65535) {
236 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
237 goto fail;
238 }
239
240 if (end < 1 || end > 65535) {
241 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
242 goto fail;
243 }
244
245 for (; port <= end; port++) {
246 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200247 l->next = curproxy->listen;
248 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
250 l->fd = -1;
251 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100252 l->state = LI_INIT;
253
254 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100256 tcpv6_add_listener(l);
257 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100259 tcpv4_add_listener(l);
260 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200261
Willy Tarreaue6b98942007-10-29 01:09:36 +0100262 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 } /* end for(port) */
264 } /* end while(next) */
265 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 fail:
268 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270}
271
Willy Tarreau977b8e42006-12-29 14:19:17 +0100272/*
273 * Sends a warning if proxy <proxy> does not have at least one of the
274 * capabilities in <cap>. An optionnal <hint> may be added at the end
275 * of the warning to help the user. Returns 1 if a warning was emitted
276 * or 0 if the condition is valid.
277 */
278int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
279{
280 char *msg;
281
282 switch (cap) {
283 case PR_CAP_BE: msg = "no backend"; break;
284 case PR_CAP_FE: msg = "no frontend"; break;
285 case PR_CAP_RS: msg = "no ruleset"; break;
286 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
287 default: msg = "not enough"; break;
288 }
289
290 if (!(proxy->cap & cap)) {
291 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100292 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100293 return 1;
294 }
295 return 0;
296}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297
Willy Tarreau61d18892009-03-31 10:49:21 +0200298/* Report a warning if a rule is placed after a 'block' rule.
299 * Return 1 if the warning has been emitted, otherwise 0.
300 */
301int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
302{
303 if (!LIST_ISEMPTY(&proxy->block_cond)) {
304 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
305 file, line, arg);
306 return 1;
307 }
308 return 0;
309}
310
311/* Report a warning if a rule is placed after a reqrewrite rule.
312 * Return 1 if the warning has been emitted, otherwise 0.
313 */
314int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
315{
316 if (proxy->req_exp) {
317 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
318 file, line, arg);
319 return 1;
320 }
321 return 0;
322}
323
324/* Report a warning if a rule is placed after a reqadd rule.
325 * Return 1 if the warning has been emitted, otherwise 0.
326 */
327int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
328{
329 if (proxy->nb_reqadd) {
330 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
331 file, line, arg);
332 return 1;
333 }
334 return 0;
335}
336
337/* Report a warning if a rule is placed after a redirect rule.
338 * Return 1 if the warning has been emitted, otherwise 0.
339 */
340int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
341{
342 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
343 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
344 file, line, arg);
345 return 1;
346 }
347 return 0;
348}
349
350/* Report a warning if a rule is placed after a 'use_backend' rule.
351 * Return 1 if the warning has been emitted, otherwise 0.
352 */
353int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
354{
355 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
356 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
357 file, line, arg);
358 return 1;
359 }
360 return 0;
361}
362
363/* report a warning if a block rule is dangerously placed */
364int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
365{
366 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
367 warnif_rule_after_reqadd(proxy, file, line, arg) ||
368 warnif_rule_after_redirect(proxy, file, line, arg) ||
369 warnif_rule_after_use_backend(proxy, file, line, arg);
370}
371
372/* report a warning if a reqxxx rule is dangerously placed */
373int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
374{
375 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
376 warnif_rule_after_redirect(proxy, file, line, arg) ||
377 warnif_rule_after_use_backend(proxy, file, line, arg);
378}
379
380/* report a warning if a reqadd rule is dangerously placed */
381int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
382{
383 return warnif_rule_after_redirect(proxy, file, line, arg) ||
384 warnif_rule_after_use_backend(proxy, file, line, arg);
385}
386
Willy Tarreaubaaee002006-06-26 02:48:02 +0200387/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200388 * parse a line in a <global> section. Returns the error code, 0 if OK, or
389 * any combination of :
390 * - ERR_ABORT: must abort ASAP
391 * - ERR_FATAL: we can continue parsing but not start the service
392 * - ERR_WARN: a warning has been emitted
393 * - ERR_ALERT: an alert has been emitted
394 * Only the two first ones can stop processing, the two others are just
395 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200396 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200397int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200398{
Willy Tarreau058e9072009-07-20 09:30:05 +0200399 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200400
401 if (!strcmp(args[0], "global")) { /* new section */
402 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200404 }
405 else if (!strcmp(args[0], "daemon")) {
406 global.mode |= MODE_DAEMON;
407 }
408 else if (!strcmp(args[0], "debug")) {
409 global.mode |= MODE_DEBUG;
410 }
411 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100412 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200413 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200414 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100415 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200416 }
417 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100418 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200420 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100421 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200422 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100423 else if (!strcmp(args[0], "nosplice")) {
424 global.tune.options &= ~GTUNE_USE_SPLICE;
425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 else if (!strcmp(args[0], "quiet")) {
427 global.mode |= MODE_QUIET;
428 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200429 else if (!strcmp(args[0], "tune.maxpollevents")) {
430 if (global.tune.maxpollevents != 0) {
431 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200432 err_code |= ERR_ALERT;
433 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200434 }
435 if (*(args[1]) == 0) {
436 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200437 err_code |= ERR_ALERT | ERR_FATAL;
438 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200439 }
440 global.tune.maxpollevents = atol(args[1]);
441 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100442 else if (!strcmp(args[0], "tune.maxaccept")) {
443 if (global.tune.maxaccept != 0) {
444 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 err_code |= ERR_ALERT;
446 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100447 }
448 if (*(args[1]) == 0) {
449 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 err_code |= ERR_ALERT | ERR_FATAL;
451 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100452 }
453 global.tune.maxaccept = atol(args[1]);
454 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200455 else if (!strcmp(args[0], "tune.bufsize")) {
456 if (*(args[1]) == 0) {
457 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
458 err_code |= ERR_ALERT | ERR_FATAL;
459 goto out;
460 }
461 global.tune.bufsize = atol(args[1]);
462 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
463 global.tune.maxrewrite = global.tune.bufsize / 2;
464 }
465 else if (!strcmp(args[0], "tune.maxrewrite")) {
466 if (*(args[1]) == 0) {
467 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
468 err_code |= ERR_ALERT | ERR_FATAL;
469 goto out;
470 }
471 global.tune.maxrewrite = atol(args[1]);
472 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
473 global.tune.maxrewrite = global.tune.bufsize / 2;
474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "uid")) {
476 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200477 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200478 err_code |= ERR_ALERT;
479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 }
481 if (*(args[1]) == 0) {
482 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 }
486 global.uid = atol(args[1]);
487 }
488 else if (!strcmp(args[0], "gid")) {
489 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200490 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200491 err_code |= ERR_ALERT;
492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 }
499 global.gid = atol(args[1]);
500 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200501 /* user/group name handling */
502 else if (!strcmp(args[0], "user")) {
503 struct passwd *ha_user;
504 if (global.uid != 0) {
505 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200506 err_code |= ERR_ALERT;
507 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200508 }
509 errno = 0;
510 ha_user = getpwnam(args[1]);
511 if (ha_user != NULL) {
512 global.uid = (int)ha_user->pw_uid;
513 }
514 else {
515 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 +0200516 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200517 }
518 }
519 else if (!strcmp(args[0], "group")) {
520 struct group *ha_group;
521 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200522 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200523 err_code |= ERR_ALERT;
524 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200525 }
526 errno = 0;
527 ha_group = getgrnam(args[1]);
528 if (ha_group != NULL) {
529 global.gid = (int)ha_group->gr_gid;
530 }
531 else {
532 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 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200534 }
535 }
536 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200537 else if (!strcmp(args[0], "nbproc")) {
538 if (global.nbproc != 0) {
539 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200540 err_code |= ERR_ALERT;
541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542 }
543 if (*(args[1]) == 0) {
544 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200545 err_code |= ERR_ALERT | ERR_FATAL;
546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 }
548 global.nbproc = atol(args[1]);
549 }
550 else if (!strcmp(args[0], "maxconn")) {
551 if (global.maxconn != 0) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200553 err_code |= ERR_ALERT;
554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 }
561 global.maxconn = atol(args[1]);
562#ifdef SYSTEM_MAXCONN
563 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
564 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);
565 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200566 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 }
568#endif /* SYSTEM_MAXCONN */
569 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100570 else if (!strcmp(args[0], "maxpipes")) {
571 if (global.maxpipes != 0) {
572 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200573 err_code |= ERR_ALERT;
574 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100580 }
581 global.maxpipes = atol(args[1]);
582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583 else if (!strcmp(args[0], "ulimit-n")) {
584 if (global.rlimit_nofile != 0) {
585 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 err_code |= ERR_ALERT;
587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 }
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 }
594 global.rlimit_nofile = atol(args[1]);
595 }
596 else if (!strcmp(args[0], "chroot")) {
597 if (global.chroot != NULL) {
598 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200599 err_code |= ERR_ALERT;
600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
602 if (*(args[1]) == 0) {
603 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 }
607 global.chroot = strdup(args[1]);
608 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200609 else if (!strcmp(args[0], "description")) {
610 int i, len=0;
611 char *d;
612
613 if (!*args[1]) {
614 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
615 file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619
620 for(i=1; *args[i]; i++)
621 len += strlen(args[i])+1;
622
623 if (global.desc)
624 free(global.desc);
625
626 global.desc = d = (char *)calloc(1, len);
627
628 d += sprintf(d, "%s", args[1]);
629 for(i=2; *args[i]; i++)
630 d += sprintf(d, " %s", args[i]);
631 }
632 else if (!strcmp(args[0], "node")) {
633 int i;
634 char c;
635
636 for (i=0; args[1][i]; i++) {
637 c = args[1][i];
638 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
639 break;
640 }
641
642 if (!i || args[1][i]) {
643 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
644 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
645 file, linenum, args[0]);
646 err_code |= ERR_ALERT | ERR_FATAL;
647 goto out;
648 }
649
650 if (global.node)
651 free(global.node);
652
653 global.node = strdup(args[1]);
654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655 else if (!strcmp(args[0], "pidfile")) {
656 if (global.pidfile != NULL) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 }
666 global.pidfile = strdup(args[1]);
667 }
668 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100669 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200670 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671
672 if (*(args[1]) == 0 || *(args[2]) == 0) {
673 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 }
677
678 facility = get_log_facility(args[2]);
679 if (facility < 0) {
680 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT | ERR_FATAL;
682 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684
685 level = 7; /* max syslog level = debug */
686 if (*(args[3])) {
687 level = get_log_level(args[3]);
688 if (level < 0) {
689 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT | ERR_FATAL;
691 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 }
694
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200695 minlvl = 0; /* limit syslog level to this level (emerg) */
696 if (*(args[4])) {
697 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200699 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200700 err_code |= ERR_ALERT | ERR_FATAL;
701 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200702 }
703 }
704
Robert Tsai81ae1952007-12-05 10:47:29 +0100705 if (args[1][0] == '/') {
706 logsrv.u.addr.sa_family = AF_UNIX;
707 logsrv.u.un = *str2sun(args[1]);
708 } else {
709 logsrv.u.addr.sa_family = AF_INET;
710 logsrv.u.in = *str2sa(args[1]);
711 if (!logsrv.u.in.sin_port)
712 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714
715 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100716 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717 global.logfac1 = facility;
718 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200719 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 }
721 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100722 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 global.logfac2 = facility;
724 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200725 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 }
727 else {
728 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200731 }
732 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
733 if (global.spread_checks != 0) {
734 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200735 err_code |= ERR_ALERT;
736 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200737 }
738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200742 }
743 global.spread_checks = atol(args[1]);
744 if (global.spread_checks < 0 || global.spread_checks > 50) {
745 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200746 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 }
749 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200750 struct cfg_kw_list *kwl;
751 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200752 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200753
754 list_for_each_entry(kwl, &cfg_keywords.list, list) {
755 for (index = 0; kwl->kw[index].kw != NULL; index++) {
756 if (kwl->kw[index].section != CFG_GLOBAL)
757 continue;
758 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
759 /* prepare error message just in case */
760 snprintf(trash, sizeof(trash),
761 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200762 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
763 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200764 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200766 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200767 else if (rc > 0) {
768 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_WARN;
770 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200771 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200772 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200773 }
774 }
775 }
776
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200780
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 out:
782 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783}
784
785
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200786void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787{
788 memset(&defproxy, 0, sizeof(defproxy));
789 defproxy.mode = PR_MODE_TCP;
790 defproxy.state = PR_STNEW;
791 defproxy.maxconn = cfg_maxpconn;
792 defproxy.conn_retries = CONN_RETRIES;
793 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200794
795 LIST_INIT(&defproxy.pendconns);
796 LIST_INIT(&defproxy.acl);
797 LIST_INIT(&defproxy.block_cond);
798 LIST_INIT(&defproxy.mon_fail_cond);
799 LIST_INIT(&defproxy.switching_rules);
800
Willy Tarreau3a70f942008-02-15 11:15:34 +0100801 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802}
803
804/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100805 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200806 * Returns the error code, 0 if OK, or any combination of :
807 * - ERR_ABORT: must abort ASAP
808 * - ERR_FATAL: we can continue parsing but not start the service
809 * - ERR_WARN: a warning has been emitted
810 * - ERR_ALERT: an alert has been emitted
811 * Only the two first ones can stop processing, the two others are just
812 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200814int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815{
816 static struct proxy *curproxy = NULL;
817 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200818 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100819 int rc;
820 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200821 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822
Willy Tarreau977b8e42006-12-29 14:19:17 +0100823 if (!strcmp(args[0], "listen"))
824 rc = PR_CAP_LISTEN;
825 else if (!strcmp(args[0], "frontend"))
826 rc = PR_CAP_FE | PR_CAP_RS;
827 else if (!strcmp(args[0], "backend"))
828 rc = PR_CAP_BE | PR_CAP_RS;
829 else if (!strcmp(args[0], "ruleset"))
830 rc = PR_CAP_RS;
831 else
832 rc = PR_CAP_NONE;
833
834 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 if (!*args[1]) {
836 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
837 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
838 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200839 err_code |= ERR_ALERT | ERR_ABORT;
840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200842
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100843 err = invalid_char(args[1]);
844 if (err) {
845 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
846 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100848 }
849
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200850 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
851 /*
852 * If there are two proxies with the same name only following
853 * combinations are allowed:
854 *
855 * listen backend frontend ruleset
856 * listen - - - -
857 * backend - - OK -
858 * frontend - OK - -
859 * ruleset - - - -
860 */
861
862 if (!strcmp(curproxy->id, args[1]) &&
863 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
864 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200865 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
866 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
867 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200868 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200869 }
870 }
871
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
873 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200874 err_code |= ERR_ALERT | ERR_ABORT;
875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100877
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 curproxy->next = proxy;
879 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200880 curproxy->conf.file = file;
881 curproxy->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200883 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200884 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200885 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100886 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200887 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200888 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889
Willy Tarreauee991362007-05-14 14:37:50 +0200890 /* Timeouts are defined as -1, so we cannot use the zeroed area
891 * as a default value.
892 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100893 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200894
895 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 Tarreau977b8e42006-12-29 14:19:17 +0100933 if (curproxy->cap & PR_CAP_FE) {
934 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100935 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200936 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100937
938 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200939 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
940 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100941
942 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944
Willy Tarreau977b8e42006-12-29 14:19:17 +0100945 if (curproxy->cap & PR_CAP_BE) {
946 curproxy->fullconn = defproxy.fullconn;
947 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948
Willy Tarreau977b8e42006-12-29 14:19:17 +0100949 if (defproxy.check_req)
950 curproxy->check_req = strdup(defproxy.check_req);
951 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952
Willy Tarreau977b8e42006-12-29 14:19:17 +0100953 if (defproxy.cookie_name)
954 curproxy->cookie_name = strdup(defproxy.cookie_name);
955 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100956
Emeric Brun647caf12009-06-30 17:57:00 +0200957 if (defproxy.rdp_cookie_name)
958 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
959 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
960
Willy Tarreau01732802007-11-01 22:48:15 +0100961 if (defproxy.url_param_name)
962 curproxy->url_param_name = strdup(defproxy.url_param_name);
963 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100964
Benoitaffb4812009-03-25 13:02:10 +0100965 if (defproxy.hh_name)
966 curproxy->hh_name = strdup(defproxy.hh_name);
967 curproxy->hh_len = defproxy.hh_len;
968 curproxy->hh_match_domain = defproxy.hh_match_domain;
969
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100970 if (defproxy.iface_name)
971 curproxy->iface_name = strdup(defproxy.iface_name);
972 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200975 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100976 if (defproxy.capture_name)
977 curproxy->capture_name = strdup(defproxy.capture_name);
978 curproxy->capture_namelen = defproxy.capture_namelen;
979 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981
Willy Tarreau977b8e42006-12-29 14:19:17 +0100982 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100983 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100984 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100985 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100986 curproxy->uri_auth = defproxy.uri_auth;
987 curproxy->mon_net = defproxy.mon_net;
988 curproxy->mon_mask = defproxy.mon_mask;
989 if (defproxy.monitor_uri)
990 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
991 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100992 if (defproxy.defbe.name)
993 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100994 }
995
996 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100997 curproxy->timeout.connect = defproxy.timeout.connect;
998 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100999 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001000 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001001 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001002 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001003 curproxy->source_addr = defproxy.source_addr;
1004 }
1005
Willy Tarreaubaaee002006-06-26 02:48:02 +02001006 curproxy->mode = defproxy.mode;
1007 curproxy->logfac1 = defproxy.logfac1;
1008 curproxy->logsrv1 = defproxy.logsrv1;
1009 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001010 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 curproxy->logfac2 = defproxy.logfac2;
1012 curproxy->logsrv2 = defproxy.logsrv2;
1013 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001014 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001016 curproxy->conf.used_listener_id = EB_ROOT;
1017 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001018
Willy Tarreau93893792009-07-23 13:19:11 +02001019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1022 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001023 /* FIXME-20070101: we should do this too at the end of the
1024 * config parsing to free all default values.
1025 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001026 free(defproxy.check_req);
1027 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001028 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001029 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001030 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001031 free(defproxy.capture_name);
1032 free(defproxy.monitor_uri);
1033 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001034 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001035 free(defproxy.fwdfor_hdr_name);
1036 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001037
Willy Tarreaua534fea2008-08-03 12:19:50 +02001038 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001039 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001040
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 /* we cannot free uri_auth because it might already be used */
1042 init_default_instance();
1043 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001044 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 }
1047 else if (curproxy == NULL) {
1048 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052
Willy Tarreau977b8e42006-12-29 14:19:17 +01001053
1054 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001056 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001057 int cur_arg;
1058
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 if (curproxy == &defproxy) {
1060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001064 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001065 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066
1067 if (strchr(args[1], ':') == NULL) {
1068 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001073
1074 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001075 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001079
Willy Tarreau90a570f2009-10-04 20:54:54 +02001080 new_listen = curproxy->listen;
1081 while (new_listen != last_listen) {
1082 new_listen->conf.file = file;
1083 new_listen->conf.line = linenum;
1084 new_listen = new_listen->next;
1085 }
1086
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001087 cur_arg = 2;
1088 while (*(args[cur_arg])) {
1089 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1090#ifdef SO_BINDTODEVICE
1091 struct listener *l;
1092
1093 if (!*args[cur_arg + 1]) {
1094 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001098 }
1099
1100 for (l = curproxy->listen; l != last_listen; l = l->next)
1101 l->interface = strdup(args[cur_arg + 1]);
1102
1103 global.last_checks |= LSTCHK_NETADM;
1104
1105 cur_arg += 2;
1106 continue;
1107#else
1108 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1109 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001112#endif
1113 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001114 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1115#ifdef TCP_MAXSEG
1116 struct listener *l;
1117 int mss;
1118
1119 if (!*args[cur_arg + 1]) {
1120 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1121 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001124 }
1125
1126 mss = str2uic(args[cur_arg + 1]);
1127 if (mss < 1 || mss > 65535) {
1128 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1129 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001132 }
1133
1134 for (l = curproxy->listen; l != last_listen; l = l->next)
1135 l->maxseg = mss;
1136
1137 cur_arg += 2;
1138 continue;
1139#else
1140 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1141 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001144#endif
1145 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001146
1147 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1148#ifdef TCP_DEFER_ACCEPT
1149 struct listener *l;
1150
1151 for (l = curproxy->listen; l != last_listen; l = l->next)
1152 l->options |= LI_O_DEF_ACCEPT;
1153
1154 cur_arg ++;
1155 continue;
1156#else
1157 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1158 file, linenum, args[0], args[cur_arg]);
1159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
1161#endif
1162 }
1163
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001164 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001165#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001166 struct listener *l;
1167
1168 for (l = curproxy->listen; l != last_listen; l = l->next)
1169 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001170
1171 cur_arg ++;
1172 continue;
1173#else
1174 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1175 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001178#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001179 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001180
1181 if (!strcmp(args[cur_arg], "name")) {
1182 struct listener *l;
1183
1184 for (l = curproxy->listen; l != last_listen; l = l->next)
1185 l->name = strdup(args[cur_arg + 1]);
1186
1187 cur_arg += 2;
1188 continue;
1189 }
1190
1191 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001192 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001193 struct listener *l;
1194
1195 if (curproxy->listen->next != last_listen) {
1196 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1197 file, linenum, args[cur_arg]);
1198 err_code |= ERR_ALERT | ERR_FATAL;
1199 goto out;
1200 }
1201
1202 if (!*args[cur_arg + 1]) {
1203 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1204 file, linenum, args[cur_arg]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208
1209 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001210 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001211
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001212 if (curproxy->listen->luid <= 0) {
1213 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001214 file, linenum);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001219 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1220 if (node) {
1221 l = container_of(node, struct listener, conf.id);
1222 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1223 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1228
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001229 cur_arg += 2;
1230 continue;
1231 }
1232
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001233 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 +01001234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001238 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 }
1241 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1242 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1243 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001247 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001248 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001249 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001250
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 /* flush useless bits */
1252 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001254 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001255 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001256 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001257 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001258
Willy Tarreau1c47f852006-07-09 08:22:27 +02001259 if (!*args[1]) {
1260 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1261 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001264 }
1265
Willy Tarreaua534fea2008-08-03 12:19:50 +02001266 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001267 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001268 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001269 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001270 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1271
Willy Tarreau93893792009-07-23 13:19:11 +02001272 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1275 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1276 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1277 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1278 else {
1279 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 }
1283 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001284 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001285 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001286
1287 if (curproxy == &defproxy) {
1288 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001292 }
1293
1294 if (!*args[1]) {
1295 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1296 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001299 }
1300
1301 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001302 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001303
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001304 if (curproxy->uuid <= 0) {
1305 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001306 file, linenum);
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
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001311 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1312 if (node) {
1313 struct proxy *target = container_of(node, struct proxy, conf.id);
1314 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1315 file, linenum, proxy_type_str(curproxy), curproxy->id,
1316 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
1320 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001321 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001322 else if (!strcmp(args[0], "description")) {
1323 int i, len=0;
1324 char *d;
1325
1326 if (!*args[1]) {
1327 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1328 file, linenum, args[0]);
1329 return -1;
1330 }
1331
1332 for(i=1; *args[i]; i++)
1333 len += strlen(args[i])+1;
1334
1335 d = (char *)calloc(1, len);
1336 curproxy->desc = d;
1337
1338 d += sprintf(d, "%s", args[1]);
1339 for(i=2; *args[i]; i++)
1340 d += sprintf(d, " %s", args[i]);
1341
1342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1344 curproxy->state = PR_STSTOPPED;
1345 }
1346 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1347 curproxy->state = PR_STNEW;
1348 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001349 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1350 int cur_arg = 1;
1351 unsigned int set = 0;
1352
1353 while (*args[cur_arg]) {
1354 int u;
1355 if (strcmp(args[cur_arg], "all") == 0) {
1356 set = 0;
1357 break;
1358 }
1359 else if (strcmp(args[cur_arg], "odd") == 0) {
1360 set |= 0x55555555;
1361 }
1362 else if (strcmp(args[cur_arg], "even") == 0) {
1363 set |= 0xAAAAAAAA;
1364 }
1365 else {
1366 u = str2uic(args[cur_arg]);
1367 if (u < 1 || u > 32) {
1368 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001372 }
1373 if (u > global.nbproc) {
1374 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1375 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001376 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001377 }
1378 set |= 1 << (u - 1);
1379 }
1380 cur_arg++;
1381 }
1382 curproxy->bind_proc = set;
1383 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001384 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001385 if (curproxy == &defproxy) {
1386 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001389 }
1390
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001391 err = invalid_char(args[1]);
1392 if (err) {
1393 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1394 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001396 }
1397
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001398 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1399 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1400 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001401 err_code |= ERR_ALERT | ERR_FATAL;
1402 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001403 }
1404 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1406 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407
Willy Tarreau977b8e42006-12-29 14:19:17 +01001408 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001409 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001410
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 if (*(args[1]) == 0) {
1412 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1413 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001417
1418 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 curproxy->cookie_name = strdup(args[1]);
1420 curproxy->cookie_len = strlen(curproxy->cookie_name);
1421
1422 cur_arg = 2;
1423 while (*(args[cur_arg])) {
1424 if (!strcmp(args[cur_arg], "rewrite")) {
1425 curproxy->options |= PR_O_COOK_RW;
1426 }
1427 else if (!strcmp(args[cur_arg], "indirect")) {
1428 curproxy->options |= PR_O_COOK_IND;
1429 }
1430 else if (!strcmp(args[cur_arg], "insert")) {
1431 curproxy->options |= PR_O_COOK_INS;
1432 }
1433 else if (!strcmp(args[cur_arg], "nocache")) {
1434 curproxy->options |= PR_O_COOK_NOC;
1435 }
1436 else if (!strcmp(args[cur_arg], "postonly")) {
1437 curproxy->options |= PR_O_COOK_POST;
1438 }
1439 else if (!strcmp(args[cur_arg], "prefix")) {
1440 curproxy->options |= PR_O_COOK_PFX;
1441 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001442 else if (!strcmp(args[cur_arg], "domain")) {
1443 if (!*args[cur_arg + 1]) {
1444 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1445 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001448 }
1449
1450 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1451 /* rfc2109, 4.3.2 Rejecting Cookies */
1452 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1453 " dots or does not start with a dot.\n",
1454 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001455 err_code |= ERR_ALERT | ERR_FATAL;
1456 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001457 }
1458
1459 err = invalid_domainchar(args[cur_arg + 1]);
1460 if (err) {
1461 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1462 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001463 err_code |= ERR_ALERT | ERR_FATAL;
1464 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001465 }
1466
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001467 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001468 cur_arg++;
1469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001471 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 }
1476 cur_arg++;
1477 }
1478 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1479 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1480 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001481 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 }
1483
1484 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1485 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1486 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001487 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 }
1489 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001490 else if (!strcmp(args[0], "persist")) { /* persist */
1491 if (*(args[1]) == 0) {
1492 Alert("parsing [%s:%d] : missing persist method.\n",
1493 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001494 err_code |= ERR_ALERT | ERR_FATAL;
1495 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001496 }
1497
1498 if (!strncmp(args[1], "rdp-cookie", 10)) {
1499 curproxy->options2 |= PR_O2_RDPC_PRST;
1500
1501 if (*(args[1] + 10 ) == '(') { /* cookie name */
1502 const char *beg, *end;
1503
1504 beg = args[1] + 11;
1505 end = strchr(beg, ')');
1506
1507 if (!end || end == beg) {
1508 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1509 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001510 err_code |= ERR_ALERT | ERR_FATAL;
1511 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001512 }
1513
1514 free(curproxy->rdp_cookie_name);
1515 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1516 curproxy->rdp_cookie_len = end-beg;
1517 }
1518 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1519 free(curproxy->rdp_cookie_name);
1520 curproxy->rdp_cookie_name = strdup("msts");
1521 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1522 }
1523 else { /* syntax */
1524 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1525 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001526 err_code |= ERR_ALERT | ERR_FATAL;
1527 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001528 }
1529 }
1530 else {
1531 Alert("parsing [%s:%d] : unknown persist method.\n",
1532 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001535 }
1536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001538 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539
Willy Tarreau977b8e42006-12-29 14:19:17 +01001540 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001541 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001542
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 if (*(args[5]) == 0) {
1544 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1545 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548 }
1549 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001550 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 curproxy->appsession_name = strdup(args[1]);
1552 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1553 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001554 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1555 if (err) {
1556 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1557 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001558 err_code |= ERR_ALERT | ERR_FATAL;
1559 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001560 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001561 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001562
Willy Tarreau51041c72007-09-09 21:56:53 +02001563 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1564 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001565 err_code |= ERR_ALERT | ERR_ABORT;
1566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001568
1569 cur_arg = 6;
1570 curproxy->options2 &= ~PR_O2_AS_REQL;
1571 while (*(args[cur_arg])) {
1572 if (!strcmp(args[cur_arg], "request-learn"))
1573 curproxy->options2 |= PR_O2_AS_REQL;
1574 cur_arg++;
1575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 } /* Url App Session */
1577 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001578 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001579 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001580
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 if (*(args[4]) == 0) {
1583 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001588 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 curproxy->capture_name = strdup(args[2]);
1590 curproxy->capture_namelen = strlen(curproxy->capture_name);
1591 curproxy->capture_len = atol(args[4]);
1592 if (curproxy->capture_len >= CAPTURE_LEN) {
1593 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1594 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 curproxy->capture_len = CAPTURE_LEN - 1;
1597 }
1598 curproxy->to_log |= LW_COOKIE;
1599 }
1600 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1601 struct cap_hdr *hdr;
1602
1603 if (curproxy == &defproxy) {
1604 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 +02001605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 }
1608
1609 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1610 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1611 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001612 err_code |= ERR_ALERT | ERR_FATAL;
1613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 }
1615
1616 hdr = calloc(sizeof(struct cap_hdr), 1);
1617 hdr->next = curproxy->req_cap;
1618 hdr->name = strdup(args[3]);
1619 hdr->namelen = strlen(args[3]);
1620 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001621 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 hdr->index = curproxy->nb_req_cap++;
1623 curproxy->req_cap = hdr;
1624 curproxy->to_log |= LW_REQHDR;
1625 }
1626 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1627 struct cap_hdr *hdr;
1628
1629 if (curproxy == &defproxy) {
1630 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 +02001631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 }
1634
1635 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1636 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1637 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 }
1641 hdr = calloc(sizeof(struct cap_hdr), 1);
1642 hdr->next = curproxy->rsp_cap;
1643 hdr->name = strdup(args[3]);
1644 hdr->namelen = strlen(args[3]);
1645 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001646 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 hdr->index = curproxy->nb_rsp_cap++;
1648 curproxy->rsp_cap = hdr;
1649 curproxy->to_log |= LW_RSPHDR;
1650 }
1651 else {
1652 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
1655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 }
1657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001659 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001661
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662 if (*(args[1]) == 0) {
1663 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1664 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 }
1668 curproxy->conn_retries = atol(args[1]);
1669 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001670 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1671 int pol = ACL_COND_NONE;
1672 struct acl_cond *cond;
1673
Willy Tarreaub099aca2008-10-12 17:26:37 +02001674 if (curproxy == &defproxy) {
1675 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001676 err_code |= ERR_ALERT | ERR_FATAL;
1677 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001678 }
1679
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001680 if (!strcmp(args[1], "if"))
1681 pol = ACL_COND_IF;
1682 else if (!strcmp(args[1], "unless"))
1683 pol = ACL_COND_UNLESS;
1684
1685 if (pol == ACL_COND_NONE) {
1686 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1687 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001690 }
1691
1692 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1693 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1694 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001697 }
Willy Tarreau88922352009-10-04 22:02:50 +02001698 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001699 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001700 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001701 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001702 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001703 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001704 else if (!strcmp(args[0], "redirect")) {
1705 int pol = ACL_COND_NONE;
1706 struct acl_cond *cond;
1707 struct redirect_rule *rule;
1708 int cur_arg;
1709 int type = REDIRECT_TYPE_NONE;
1710 int code = 302;
1711 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001712 char *cookie = NULL;
1713 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001714 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001715
1716 cur_arg = 1;
1717 while (*(args[cur_arg])) {
1718 if (!strcmp(args[cur_arg], "location")) {
1719 if (!*args[cur_arg + 1]) {
1720 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1721 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001724 }
1725
1726 type = REDIRECT_TYPE_LOCATION;
1727 cur_arg++;
1728 destination = args[cur_arg];
1729 }
1730 else if (!strcmp(args[cur_arg], "prefix")) {
1731 if (!*args[cur_arg + 1]) {
1732 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1733 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001736 }
1737
1738 type = REDIRECT_TYPE_PREFIX;
1739 cur_arg++;
1740 destination = args[cur_arg];
1741 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001742 else if (!strcmp(args[cur_arg], "set-cookie")) {
1743 if (!*args[cur_arg + 1]) {
1744 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1745 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001746 err_code |= ERR_ALERT | ERR_FATAL;
1747 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001748 }
1749
1750 cur_arg++;
1751 cookie = args[cur_arg];
1752 cookie_set = 1;
1753 }
1754 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1755 if (!*args[cur_arg + 1]) {
1756 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1757 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001758 err_code |= ERR_ALERT | ERR_FATAL;
1759 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001760 }
1761
1762 cur_arg++;
1763 cookie = args[cur_arg];
1764 cookie_set = 0;
1765 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001766 else if (!strcmp(args[cur_arg],"code")) {
1767 if (!*args[cur_arg + 1]) {
1768 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1769 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001772 }
1773 cur_arg++;
1774 code = atol(args[cur_arg]);
1775 if (code < 301 || code > 303) {
1776 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1777 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001778 err_code |= ERR_ALERT | ERR_FATAL;
1779 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001780 }
1781 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001782 else if (!strcmp(args[cur_arg],"drop-query")) {
1783 flags |= REDIRECT_FLAG_DROP_QS;
1784 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001785 else if (!strcmp(args[cur_arg], "if")) {
1786 pol = ACL_COND_IF;
1787 cur_arg++;
1788 break;
1789 }
1790 else if (!strcmp(args[cur_arg], "unless")) {
1791 pol = ACL_COND_UNLESS;
1792 cur_arg++;
1793 break;
1794 }
1795 else {
1796 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1797 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001800 }
1801 cur_arg++;
1802 }
1803
1804 if (type == REDIRECT_TYPE_NONE) {
1805 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1806 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001809 }
1810
1811 if (pol == ACL_COND_NONE) {
1812 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1813 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001816 }
1817
1818 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001819 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001820 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001823 }
1824
Willy Tarreau88922352009-10-04 22:02:50 +02001825 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001826 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001827 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001828 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1829 rule->cond = cond;
1830 rule->rdr_str = strdup(destination);
1831 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001832 if (cookie) {
1833 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1834 * a clear consists in appending "; Max-Age=0" at the end.
1835 */
1836 rule->cookie_len = strlen(cookie);
1837 if (cookie_set)
1838 rule->cookie_str = strdup(cookie);
1839 else {
1840 rule->cookie_str = malloc(rule->cookie_len + 12);
1841 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1842 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1843 rule->cookie_len += 11;
1844 }
1845 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001846 rule->type = type;
1847 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001848 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001849 LIST_INIT(&rule->list);
1850 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001851 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001852 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001853 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001854 int pol = ACL_COND_NONE;
1855 struct acl_cond *cond;
1856 struct switching_rule *rule;
1857
Willy Tarreaub099aca2008-10-12 17:26:37 +02001858 if (curproxy == &defproxy) {
1859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001862 }
1863
Willy Tarreau55ea7572007-06-17 19:56:27 +02001864 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001865 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001866
1867 if (*(args[1]) == 0) {
1868 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001871 }
1872
1873 if (!strcmp(args[2], "if"))
1874 pol = ACL_COND_IF;
1875 else if (!strcmp(args[2], "unless"))
1876 pol = ACL_COND_UNLESS;
1877
1878 if (pol == ACL_COND_NONE) {
1879 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1880 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001881 err_code |= ERR_ALERT | ERR_FATAL;
1882 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001883 }
1884
1885 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001886 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001887 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001890 }
1891
Willy Tarreau88922352009-10-04 22:02:50 +02001892 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001893 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001894 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001895 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001896 struct acl *acl;
1897 const char *name;
1898
1899 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1900 name = acl ? acl->name : "(unknown)";
1901 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1902 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001903 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001904 }
1905
Willy Tarreau55ea7572007-06-17 19:56:27 +02001906 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1907 rule->cond = cond;
1908 rule->be.name = strdup(args[1]);
1909 LIST_INIT(&rule->list);
1910 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001914 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001915
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1917 curproxy->uri_auth = NULL; /* we must detach from the default config */
1918
1919 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001920 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 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 } else if (!strcmp(args[1], "uri")) {
1924 if (*(args[2]) == 0) {
1925 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1929 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_ALERT | ERR_ABORT;
1931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 }
1933 } else if (!strcmp(args[1], "realm")) {
1934 if (*(args[2]) == 0) {
1935 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1939 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_ABORT;
1941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001943 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001944 unsigned interval;
1945
1946 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1947 if (err) {
1948 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1949 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001952 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1953 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_ALERT | ERR_ABORT;
1955 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 } else if (!strcmp(args[1], "auth")) {
1958 if (*(args[2]) == 0) {
1959 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1963 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001964 err_code |= ERR_ALERT | ERR_ABORT;
1965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 }
1967 } else if (!strcmp(args[1], "scope")) {
1968 if (*(args[2]) == 0) {
1969 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1973 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_ABORT;
1975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 }
1977 } else if (!strcmp(args[1], "enable")) {
1978 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1979 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_ABORT;
1981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001983 } else if (!strcmp(args[1], "hide-version")) {
1984 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
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;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001988 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001989 } else if (!strcmp(args[1], "show-node")) {
1990
1991 if (*args[2]) {
1992 int i;
1993 char c;
1994
1995 for (i=0; args[2][i]; i++) {
1996 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02001997 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001998 break;
1999 }
2000
2001 if (!i || args[2][i]) {
2002 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2003 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2004 file, linenum, args[0], args[1]);
2005 err_code |= ERR_ALERT | ERR_FATAL;
2006 goto out;
2007 }
2008 }
2009
2010 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2011 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2012 err_code |= ERR_ALERT | ERR_ABORT;
2013 goto out;
2014 }
2015 } else if (!strcmp(args[1], "show-desc")) {
2016 char *desc = NULL;
2017
2018 if (*args[2]) {
2019 int i, len=0;
2020 char *d;
2021
2022 for(i=2; *args[i]; i++)
2023 len += strlen(args[i])+1;
2024
2025 desc = d = (char *)calloc(1, len);
2026
2027 d += sprintf(d, "%s", args[2]);
2028 for(i=3; *args[i]; i++)
2029 d += sprintf(d, " %s", args[i]);
2030 }
2031
2032 if (!*args[2] && !global.desc)
2033 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2034 file, linenum, args[1]);
2035 else {
2036 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2037 free(desc);
2038 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2039 err_code |= ERR_ALERT | ERR_ABORT;
2040 goto out;
2041 }
2042 free(desc);
2043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002045 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 }
2050 }
2051 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002052 int optnum;
2053
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002054 if (*(args[1]) == '\0') {
2055 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2056 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002060
2061 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2062 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002063 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2064 err_code |= ERR_WARN;
2065 goto out;
2066 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002067
Willy Tarreau3842f002009-06-14 11:39:52 +02002068 curproxy->no_options &= ~cfg_opts[optnum].val;
2069 curproxy->options &= ~cfg_opts[optnum].val;
2070
2071 switch (kwm) {
2072 case KWM_STD:
2073 curproxy->options |= cfg_opts[optnum].val;
2074 break;
2075 case KWM_NO:
2076 curproxy->no_options |= cfg_opts[optnum].val;
2077 break;
2078 case KWM_DEF: /* already cleared */
2079 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002080 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002081
Willy Tarreau93893792009-07-23 13:19:11 +02002082 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002083 }
2084 }
2085
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002086 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2087 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002088 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2089 err_code |= ERR_WARN;
2090 goto out;
2091 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002092
Willy Tarreau3842f002009-06-14 11:39:52 +02002093 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2094 curproxy->options2 &= ~cfg_opts2[optnum].val;
2095
2096 switch (kwm) {
2097 case KWM_STD:
2098 curproxy->options2 |= cfg_opts2[optnum].val;
2099 break;
2100 case KWM_NO:
2101 curproxy->no_options2 |= cfg_opts2[optnum].val;
2102 break;
2103 case KWM_DEF: /* already cleared */
2104 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002105 }
Willy Tarreau93893792009-07-23 13:19:11 +02002106 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002107 }
2108 }
2109
Willy Tarreau3842f002009-06-14 11:39:52 +02002110 if (kwm != KWM_STD) {
2111 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002112 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002115 }
2116
Emeric Brun3a058f32009-06-30 18:26:00 +02002117 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002119 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002121 if (*(args[2]) != '\0') {
2122 if (!strcmp(args[2], "clf")) {
2123 curproxy->options2 |= PR_O2_CLFLOG;
2124 } else {
2125 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002128 }
2129 }
2130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 else if (!strcmp(args[1], "tcplog"))
2132 /* generate a detailed TCP log */
2133 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 else if (!strcmp(args[1], "tcpka")) {
2135 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002136 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002138
2139 if (curproxy->cap & PR_CAP_FE)
2140 curproxy->options |= PR_O_TCP_CLI_KA;
2141 if (curproxy->cap & PR_CAP_BE)
2142 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 }
2144 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002145 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_WARN;
2147
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002149 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002150 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002151 curproxy->options &= ~PR_O_SMTP_CHK;
2152 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 if (!*args[2]) { /* no argument */
2154 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2155 curproxy->check_len = strlen(DEF_CHECK_REQ);
2156 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002157 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 curproxy->check_req = (char *)malloc(reqlen);
2159 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2160 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2161 } else { /* more arguments : METHOD URI [HTTP_VER] */
2162 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2163 if (*args[4])
2164 reqlen += strlen(args[4]);
2165 else
2166 reqlen += strlen("HTTP/1.0");
2167
2168 curproxy->check_req = (char *)malloc(reqlen);
2169 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2170 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2171 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002172 }
2173 else if (!strcmp(args[1], "ssl-hello-chk")) {
2174 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002175 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002177
Willy Tarreaua534fea2008-08-03 12:19:50 +02002178 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002179 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002180 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002181 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 }
Willy Tarreau23677902007-05-08 23:50:35 +02002183 else if (!strcmp(args[1], "smtpchk")) {
2184 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002185 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002186 curproxy->options &= ~PR_O_HTTP_CHK;
2187 curproxy->options &= ~PR_O_SSL3_CHK;
2188 curproxy->options |= PR_O_SMTP_CHK;
2189
2190 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2191 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2192 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2193 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2194 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2195 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2196 curproxy->check_req = (char *)malloc(reqlen);
2197 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2198 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2199 } else {
2200 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2201 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2202 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2203 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2204 }
2205 }
2206 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002207 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002208 int cur_arg;
2209
2210 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2211 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002212 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002213
2214 curproxy->options |= PR_O_FWDFOR;
2215
2216 free(curproxy->fwdfor_hdr_name);
2217 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2218 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2219
2220 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2221 cur_arg = 2;
2222 while (*(args[cur_arg])) {
2223 if (!strcmp(args[cur_arg], "except")) {
2224 /* suboption except - needs additional argument for it */
2225 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2226 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2227 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002230 }
2231 /* flush useless bits */
2232 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002233 cur_arg += 2;
2234 } else if (!strcmp(args[cur_arg], "header")) {
2235 /* suboption header - needs additional argument for it */
2236 if (*(args[cur_arg+1]) == 0) {
2237 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2238 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002241 }
2242 free(curproxy->fwdfor_hdr_name);
2243 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2244 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2245 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002246 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002247 /* unknown suboption - catchall */
2248 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2249 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002252 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002253 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002254 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002255 else if (!strcmp(args[1], "originalto")) {
2256 int cur_arg;
2257
2258 /* insert x-original-to field, but not for the IP address listed as an except.
2259 * set default options (ie: bitfield, header name, etc)
2260 */
2261
2262 curproxy->options |= PR_O_ORGTO;
2263
2264 free(curproxy->orgto_hdr_name);
2265 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2266 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2267
2268 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2269 cur_arg = 2;
2270 while (*(args[cur_arg])) {
2271 if (!strcmp(args[cur_arg], "except")) {
2272 /* suboption except - needs additional argument for it */
2273 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2274 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2275 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002276 err_code |= ERR_ALERT | ERR_FATAL;
2277 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002278 }
2279 /* flush useless bits */
2280 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2281 cur_arg += 2;
2282 } else if (!strcmp(args[cur_arg], "header")) {
2283 /* suboption header - needs additional argument for it */
2284 if (*(args[cur_arg+1]) == 0) {
2285 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2286 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002289 }
2290 free(curproxy->orgto_hdr_name);
2291 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2292 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2293 cur_arg += 2;
2294 } else {
2295 /* unknown suboption - catchall */
2296 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2297 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002300 }
2301 } /* end while loop */
2302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 else {
2304 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307 }
Willy Tarreau93893792009-07-23 13:19:11 +02002308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002310 else if (!strcmp(args[0], "default_backend")) {
2311 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002313
2314 if (*(args[1]) == 0) {
2315 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002318 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002319 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002320 curproxy->defbe.name = strdup(args[1]);
2321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002323 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002325
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002326 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2327 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 /* enable reconnections to dispatch */
2330 curproxy->options |= PR_O_REDISP;
2331 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002332 else if (!strcmp(args[0], "http-check")) {
2333 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002334 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002335
2336 if (strcmp(args[1], "disable-on-404") == 0) {
2337 /* enable a graceful server shutdown on an HTTP 404 response */
2338 curproxy->options |= PR_O_DISABLE404;
2339 }
2340 else {
2341 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002344 }
2345 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002346 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002347 if (curproxy == &defproxy) {
2348 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002351 }
2352
Willy Tarreaub80c2302007-11-30 20:51:32 +01002353 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002355
2356 if (strcmp(args[1], "fail") == 0) {
2357 /* add a condition to fail monitor requests */
2358 int pol = ACL_COND_NONE;
2359 struct acl_cond *cond;
2360
2361 if (!strcmp(args[2], "if"))
2362 pol = ACL_COND_IF;
2363 else if (!strcmp(args[2], "unless"))
2364 pol = ACL_COND_UNLESS;
2365
2366 if (pol == ACL_COND_NONE) {
2367 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2368 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002371 }
2372
2373 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2374 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2375 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002378 }
Willy Tarreau88922352009-10-04 22:02:50 +02002379 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002380 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002381 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002382 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2383 }
2384 else {
2385 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002388 }
2389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390#ifdef TPROXY
2391 else if (!strcmp(args[0], "transparent")) {
2392 /* enable transparent proxy connections */
2393 curproxy->options |= PR_O_TRANSP;
2394 }
2395#endif
2396 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002397 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002399
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 if (*(args[1]) == 0) {
2401 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 }
2405 curproxy->maxconn = atol(args[1]);
2406 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002407 else if (!strcmp(args[0], "backlog")) { /* backlog */
2408 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002410
2411 if (*(args[1]) == 0) {
2412 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002415 }
2416 curproxy->backlog = atol(args[1]);
2417 }
Willy Tarreau86034312006-12-29 00:10:33 +01002418 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002419 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002421
Willy Tarreau86034312006-12-29 00:10:33 +01002422 if (*(args[1]) == 0) {
2423 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002426 }
2427 curproxy->fullconn = atol(args[1]);
2428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2430 if (*(args[1]) == 0) {
2431 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002435 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2436 if (err) {
2437 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2438 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002441 }
2442 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 }
2444 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2445 if (curproxy == &defproxy) {
2446 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002452
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 if (strchr(args[1], ':') == NULL) {
2454 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
2458 curproxy->dispatch_addr = *str2sa(args[1]);
2459 }
2460 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002461 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002463
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002464 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002465 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2466 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002471 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2472 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2473 err_code |= ERR_WARN;
2474
2475 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2476 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2477 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2478 }
2479 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2480 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2481 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2482 }
2483 else {
2484 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 else if (!strcmp(args[0], "server")) { /* server address */
2490 int cur_arg;
2491 char *rport;
2492 char *raddr;
2493 short realport;
2494 int do_check;
2495
2496 if (curproxy == &defproxy) {
2497 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002501 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002502 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503
2504 if (!*args[2]) {
2505 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2506 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002510
2511 err = invalid_char(args[1]);
2512 if (err) {
2513 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2514 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002517 }
2518
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2520 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_ABORT;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524
2525 /* the servers are linked backwards first */
2526 newsrv->next = curproxy->srv;
2527 curproxy->srv = newsrv;
2528 newsrv->proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002529 newsrv->conf.file = file;
2530 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531
2532 LIST_INIT(&newsrv->pendconns);
2533 do_check = 0;
2534 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002535 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 newsrv->id = strdup(args[1]);
2537
2538 /* several ways to check the port component :
2539 * - IP => port=+0, relative
2540 * - IP: => port=+0, relative
2541 * - IP:N => port=N, absolute
2542 * - IP:+N => port=+N, relative
2543 * - IP:-N => port=-N, relative
2544 */
2545 raddr = strdup(args[2]);
2546 rport = strchr(raddr, ':');
2547 if (rport) {
2548 *rport++ = 0;
2549 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002550 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 newsrv->state |= SRV_MAPPORTS;
2552 } else {
2553 realport = 0;
2554 newsrv->state |= SRV_MAPPORTS;
2555 }
2556
2557 newsrv->addr = *str2sa(raddr);
2558 newsrv->addr.sin_port = htons(realport);
2559 free(raddr);
2560
2561 newsrv->curfd = -1; /* no health-check in progress */
2562 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002563 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2564 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 newsrv->rise = DEF_RISETIME;
2566 newsrv->fall = DEF_FALLTIME;
2567 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau975c50b2009-10-10 19:34:06 +02002568 newsrv->uweight = newsrv->iweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002569 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002570 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002571
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 cur_arg = 3;
2573 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002574 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002575 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002576
2577 if (!*args[cur_arg + 1]) {
2578 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2579 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002582 }
2583
2584 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002585 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002586
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002587 if (newsrv->puid <= 0) {
2588 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002589 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002592 }
2593
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002594 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2595 if (node) {
2596 struct server *target = container_of(node, struct server, conf.id);
2597 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2598 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
2602 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002603 cur_arg += 2;
2604 }
2605 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 newsrv->cookie = strdup(args[cur_arg + 1]);
2607 newsrv->cklen = strlen(args[cur_arg + 1]);
2608 cur_arg += 2;
2609 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002610 else if (!strcmp(args[cur_arg], "redir")) {
2611 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2612 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2613 cur_arg += 2;
2614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002616 if (!*args[cur_arg + 1]) {
2617 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2618 file, linenum, args[cur_arg]);
2619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
2621 }
2622
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002624 if (newsrv->rise <= 0) {
2625 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2626 file, linenum, args[cur_arg]);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 newsrv->health = newsrv->rise;
2632 cur_arg += 2;
2633 }
2634 else if (!strcmp(args[cur_arg], "fall")) {
2635 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002636
2637 if (!*args[cur_arg + 1]) {
2638 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2639 file, linenum, args[cur_arg]);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643
2644 if (newsrv->fall <= 0) {
2645 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2646 file, linenum, args[cur_arg]);
2647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
2649 }
2650
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 cur_arg += 2;
2652 }
2653 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002654 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2655 if (err) {
2656 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2657 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002660 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002661 if (val <= 0) {
2662 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2663 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002666 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002667 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 cur_arg += 2;
2669 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002670 else if (!strcmp(args[cur_arg], "fastinter")) {
2671 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2672 if (err) {
2673 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2674 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002677 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002678 if (val <= 0) {
2679 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2680 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002683 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002684 newsrv->fastinter = val;
2685 cur_arg += 2;
2686 }
2687 else if (!strcmp(args[cur_arg], "downinter")) {
2688 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2689 if (err) {
2690 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2691 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002694 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002695 if (val <= 0) {
2696 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2697 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002700 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002701 newsrv->downinter = val;
2702 cur_arg += 2;
2703 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002704 else if (!strcmp(args[cur_arg], "addr")) {
2705 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002706 cur_arg += 2;
2707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 else if (!strcmp(args[cur_arg], "port")) {
2709 newsrv->check_port = atol(args[cur_arg + 1]);
2710 cur_arg += 2;
2711 }
2712 else if (!strcmp(args[cur_arg], "backup")) {
2713 newsrv->state |= SRV_BACKUP;
2714 cur_arg ++;
2715 }
2716 else if (!strcmp(args[cur_arg], "weight")) {
2717 int w;
2718 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002719 if (w < 0 || w > 256) {
2720 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002725 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 cur_arg += 2;
2727 }
2728 else if (!strcmp(args[cur_arg], "minconn")) {
2729 newsrv->minconn = atol(args[cur_arg + 1]);
2730 cur_arg += 2;
2731 }
2732 else if (!strcmp(args[cur_arg], "maxconn")) {
2733 newsrv->maxconn = atol(args[cur_arg + 1]);
2734 cur_arg += 2;
2735 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002736 else if (!strcmp(args[cur_arg], "maxqueue")) {
2737 newsrv->maxqueue = atol(args[cur_arg + 1]);
2738 cur_arg += 2;
2739 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002740 else if (!strcmp(args[cur_arg], "slowstart")) {
2741 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002742 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002743 if (err) {
2744 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2745 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002748 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002749 if (val <= 0) {
2750 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2751 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002754 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002755 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002756 cur_arg += 2;
2757 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002758 else if (!strcmp(args[cur_arg], "track")) {
2759
2760 if (!*args[cur_arg + 1]) {
2761 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2762 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002765 }
2766
2767 newsrv->trackit = strdup(args[cur_arg + 1]);
2768
2769 cur_arg += 2;
2770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 else if (!strcmp(args[cur_arg], "check")) {
2772 global.maxsock++;
2773 do_check = 1;
2774 cur_arg += 1;
2775 }
2776 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002777 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002779#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002780 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002781 file, linenum, "source", "usesrc");
2782#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002783 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002785#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002786 err_code |= ERR_ALERT | ERR_FATAL;
2787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 }
2789 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002790 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2791
2792 if (port_low != port_high) {
2793 int i;
2794 if (port_low <= 0 || port_low > 65535 ||
2795 port_high <= 0 || port_high > 65535 ||
2796 port_low > port_high) {
2797 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2798 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002801 }
2802 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2803 for (i = 0; i < newsrv->sport_range->size; i++)
2804 newsrv->sport_range->ports[i] = port_low + i;
2805 }
2806
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002808 while (*(args[cur_arg])) {
2809 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002810#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2811#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002812 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2813 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2814 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002817 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002818#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002819 if (!*args[cur_arg + 1]) {
2820 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2821 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002824 }
2825 if (!strcmp(args[cur_arg + 1], "client")) {
2826 newsrv->state |= SRV_TPROXY_CLI;
2827 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2828 newsrv->state |= SRV_TPROXY_CIP;
2829 } else {
2830 newsrv->state |= SRV_TPROXY_ADDR;
2831 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2832 }
2833 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002834#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002835 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002836#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002837 cur_arg += 2;
2838 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002839#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002840 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002841 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002844#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2845 } /* "usesrc" */
2846
2847 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2848#ifdef SO_BINDTODEVICE
2849 if (!*args[cur_arg + 1]) {
2850 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2851 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002854 }
2855 if (newsrv->iface_name)
2856 free(newsrv->iface_name);
2857
2858 newsrv->iface_name = strdup(args[cur_arg + 1]);
2859 newsrv->iface_len = strlen(newsrv->iface_name);
2860 global.last_checks |= LSTCHK_NETADM;
2861#else
2862 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2863 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002866#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002867 cur_arg += 2;
2868 continue;
2869 }
2870 /* this keyword in not an option of "source" */
2871 break;
2872 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002874 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2875 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2876 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002881 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 +02002882 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 }
2886 }
2887
2888 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002889 if (newsrv->trackit) {
2890 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2891 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002894 }
2895
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002896 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2897 newsrv->check_port = newsrv->check_addr.sin_port;
2898
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2900 newsrv->check_port = realport; /* by default */
2901 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002902 /* not yet valid, because no port was set on
2903 * the server either. We'll check if we have
2904 * a known port on the first listener.
2905 */
2906 struct listener *l;
2907 l = curproxy->listen;
2908 if (l) {
2909 int port;
2910 port = (l->addr.ss_family == AF_INET6)
2911 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2912 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2913 newsrv->check_port = port;
2914 }
2915 }
2916 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2918 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02002922
2923 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 newsrv->state |= SRV_CHECKED;
2925 }
2926
2927 if (newsrv->state & SRV_BACKUP)
2928 curproxy->srv_bck++;
2929 else
2930 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002931
2932 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 }
2934 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002935 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 int facility;
2937
2938 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2939 curproxy->logfac1 = global.logfac1;
2940 curproxy->logsrv1 = global.logsrv1;
2941 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002942 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 curproxy->logfac2 = global.logfac2;
2944 curproxy->logsrv2 = global.logsrv2;
2945 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002946 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 }
2948 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002949 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950
2951 facility = get_log_facility(args[2]);
2952 if (facility < 0) {
2953 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2954 exit(1);
2955 }
2956
2957 level = 7; /* max syslog level = debug */
2958 if (*(args[3])) {
2959 level = get_log_level(args[3]);
2960 if (level < 0) {
2961 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2962 exit(1);
2963 }
2964 }
2965
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002966 minlvl = 0; /* limit syslog level to this level (emerg) */
2967 if (*(args[4])) {
2968 minlvl = get_log_level(args[4]);
2969 if (level < 0) {
2970 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2971 exit(1);
2972 }
2973 }
2974
Robert Tsai81ae1952007-12-05 10:47:29 +01002975 if (args[1][0] == '/') {
2976 logsrv.u.addr.sa_family = AF_UNIX;
2977 logsrv.u.un = *str2sun(args[1]);
2978 } else {
2979 logsrv.u.addr.sa_family = AF_INET;
2980 logsrv.u.in = *str2sa(args[1]);
2981 if (!logsrv.u.in.sin_port) {
2982 logsrv.u.in.sin_port =
2983 htons(SYSLOG_PORT);
2984 }
2985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002986
2987 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002988 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 curproxy->logfac1 = facility;
2990 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002991 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 }
2993 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002994 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 curproxy->logfac2 = facility;
2996 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002997 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
2999 else {
3000 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 }
3004 }
3005 else {
3006 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3007 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
3011 }
3012 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003013 int cur_arg;
3014
Willy Tarreau977b8e42006-12-29 14:19:17 +01003015 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003017
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003019 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3020 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003024
3025 /* we must first clear any optional default setting */
3026 curproxy->options &= ~PR_O_TPXY_MASK;
3027 free(curproxy->iface_name);
3028 curproxy->iface_name = NULL;
3029 curproxy->iface_len = 0;
3030
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 curproxy->source_addr = *str2sa(args[1]);
3032 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003033
3034 cur_arg = 2;
3035 while (*(args[cur_arg])) {
3036 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003037#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3038#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003039 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3040 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3041 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003044 }
3045#endif
3046 if (!*args[cur_arg + 1]) {
3047 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3048 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003051 }
3052
3053 if (!strcmp(args[cur_arg + 1], "client")) {
3054 curproxy->options |= PR_O_TPXY_CLI;
3055 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3056 curproxy->options |= PR_O_TPXY_CIP;
3057 } else {
3058 curproxy->options |= PR_O_TPXY_ADDR;
3059 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3060 }
3061 global.last_checks |= LSTCHK_NETADM;
3062#if !defined(CONFIG_HAP_LINUX_TPROXY)
3063 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003064#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003065#else /* no TPROXY support */
3066 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003067 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003070#endif
3071 cur_arg += 2;
3072 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003073 }
3074
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003075 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3076#ifdef SO_BINDTODEVICE
3077 if (!*args[cur_arg + 1]) {
3078 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003082 }
3083 if (curproxy->iface_name)
3084 free(curproxy->iface_name);
3085
3086 curproxy->iface_name = strdup(args[cur_arg + 1]);
3087 curproxy->iface_len = strlen(curproxy->iface_name);
3088 global.last_checks |= LSTCHK_NETADM;
3089#else
3090 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3091 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003094#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003095 cur_arg += 2;
3096 continue;
3097 }
3098 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3099 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003104 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3105 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3106 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3111 regex_t *preg;
3112 if (curproxy == &defproxy) {
3113 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003117 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003119
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 if (*(args[1]) == 0 || *(args[2]) == 0) {
3121 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3122 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 }
3126
3127 preg = calloc(1, sizeof(regex_t));
3128 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3129 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }
3133
3134 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3135 if (err) {
3136 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3137 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003140 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 }
3142 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3143 regex_t *preg;
3144 if (curproxy == &defproxy) {
3145 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003149 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003151
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 if (*(args[1]) == 0) {
3153 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 }
3157
3158 preg = calloc(1, sizeof(regex_t));
3159 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3160 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 }
3164
3165 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003166 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
3168 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3169 regex_t *preg;
3170 if (curproxy == &defproxy) {
3171 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003175 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 if (*(args[1]) == 0) {
3179 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 }
3183
3184 preg = calloc(1, sizeof(regex_t));
3185 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3186 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 }
3190
3191 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003192 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
3194 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3195 regex_t *preg;
3196 if (curproxy == &defproxy) {
3197 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003201 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003203
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 if (*(args[1]) == 0) {
3205 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
3209
3210 preg = calloc(1, sizeof(regex_t));
3211 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3212 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
3216
3217 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003218 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 }
3220 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3221 regex_t *preg;
3222 if (curproxy == &defproxy) {
3223 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003227 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003229
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 if (*(args[1]) == 0) {
3231 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 }
3235
3236 preg = calloc(1, sizeof(regex_t));
3237 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3238 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 }
3242
3243 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003244 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003246 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3247 regex_t *preg;
3248 if (curproxy == &defproxy) {
3249 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003252 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003253 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003255
Willy Tarreaub8750a82006-09-03 09:56:00 +02003256 if (*(args[1]) == 0) {
3257 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003260 }
3261
3262 preg = calloc(1, sizeof(regex_t));
3263 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3264 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003267 }
3268
3269 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003270 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003271 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003272 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3273 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003274 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003275 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003278 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003279 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003281
Willy Tarreau977b8e42006-12-29 14:19:17 +01003282 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003283 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3284 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003287 }
3288
3289 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003290 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003291 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003292 err_code |= ERR_ALERT | ERR_FATAL;
3293 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003294 }
3295
3296 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003297 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003298 }
3299 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3300 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003301 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003302 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003305 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003306 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003308
Willy Tarreau977b8e42006-12-29 14:19:17 +01003309 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003310 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3311 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003314 }
3315
3316 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003317 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003318 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003321 }
3322
3323 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003324 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3327 regex_t *preg;
3328 if (curproxy == &defproxy) {
3329 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003333 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003334 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003335
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 if (*(args[1]) == 0 || *(args[2]) == 0) {
3337 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3338 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 | REG_ICASE) != 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 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3351 if (err) {
3352 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3353 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003357 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 }
3359 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3360 regex_t *preg;
3361 if (curproxy == &defproxy) {
3362 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003366 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003368
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 if (*(args[1]) == 0) {
3370 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
3374
3375 preg = calloc(1, sizeof(regex_t));
3376 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3377 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 }
3381
3382 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003383 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 }
3385 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3386 regex_t *preg;
3387 if (curproxy == &defproxy) {
3388 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003392 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003394
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 if (*(args[1]) == 0) {
3396 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400
3401 preg = calloc(1, sizeof(regex_t));
3402 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3403 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003404 err_code |= ERR_ALERT | ERR_FATAL;
3405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
3407
3408 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003409 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 }
3411 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3412 regex_t *preg;
3413 if (curproxy == &defproxy) {
3414 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003418 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003420
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 if (*(args[1]) == 0) {
3422 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 }
3426
3427 preg = calloc(1, sizeof(regex_t));
3428 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3429 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
3433
3434 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003435 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 }
3437 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3438 regex_t *preg;
3439 if (curproxy == &defproxy) {
3440 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003443 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003444 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003445 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003446
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 if (*(args[1]) == 0) {
3448 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 }
3452
3453 preg = calloc(1, sizeof(regex_t));
3454 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3455 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 }
3459
3460 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003461 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003463 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3464 regex_t *preg;
3465 if (curproxy == &defproxy) {
3466 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003469 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003470 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003472
Willy Tarreaub8750a82006-09-03 09:56:00 +02003473 if (*(args[1]) == 0) {
3474 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003477 }
3478
3479 preg = calloc(1, sizeof(regex_t));
3480 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3481 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003484 }
3485
3486 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003487 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3490 if (curproxy == &defproxy) {
3491 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003495 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497
3498 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3499 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 }
3503
3504 if (*(args[1]) == 0) {
3505 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 }
3509
3510 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003511 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 }
3513 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3514 regex_t *preg;
3515
3516 if (*(args[1]) == 0 || *(args[2]) == 0) {
3517 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3518 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003522 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003524
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 preg = calloc(1, sizeof(regex_t));
3526 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3527 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 }
3531
3532 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3533 if (err) {
3534 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3535 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003539 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 }
3541 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3542 regex_t *preg;
3543 if (curproxy == &defproxy) {
3544 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003548 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003550
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 if (*(args[1]) == 0) {
3552 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
3556
3557 preg = calloc(1, sizeof(regex_t));
3558 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3559 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 }
3563
3564 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3565 if (err) {
3566 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3567 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 }
3571 }
3572 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3573 regex_t *preg;
3574 if (curproxy == &defproxy) {
3575 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003579 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003581
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 if (*(args[1]) == 0) {
3583 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
3587
3588 preg = calloc(1, sizeof(regex_t));
3589 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3590 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 }
3594
3595 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3596 if (err) {
3597 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3598 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 }
3602 }
3603 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3604 regex_t *preg;
3605 if (curproxy == &defproxy) {
3606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003610 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612
3613 if (*(args[1]) == 0 || *(args[2]) == 0) {
3614 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3615 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 }
3619
3620 preg = calloc(1, sizeof(regex_t));
3621 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3622 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 }
3626
3627 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3628 if (err) {
3629 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3630 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
3634 }
3635 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3636 regex_t *preg;
3637 if (curproxy == &defproxy) {
3638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003642 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003644
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 if (*(args[1]) == 0) {
3646 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650
3651 preg = calloc(1, sizeof(regex_t));
3652 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3653 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
3657
3658 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3659 if (err) {
3660 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3661 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 }
3665 }
3666 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3667 regex_t *preg;
3668 if (curproxy == &defproxy) {
3669 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003673 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003675
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 if (*(args[1]) == 0) {
3677 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003680 }
3681
3682 preg = calloc(1, sizeof(regex_t));
3683 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3684 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 }
3688
3689 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3690 if (err) {
3691 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3692 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 }
3696 }
3697 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3698 if (curproxy == &defproxy) {
3699 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003703 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705
3706 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3707 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 }
3711
3712 if (*(args[1]) == 0) {
3713 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
3717
3718 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3719 }
3720 else if (!strcmp(args[0], "errorloc") ||
3721 !strcmp(args[0], "errorloc302") ||
3722 !strcmp(args[0], "errorloc303")) { /* error location */
3723 int errnum, errlen;
3724 char *err;
3725
Willy Tarreau977b8e42006-12-29 14:19:17 +01003726 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003728
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003730 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003733 }
3734
3735 errnum = atol(args[1]);
3736 if (!strcmp(args[0], "errorloc303")) {
3737 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3738 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3739 } else {
3740 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3741 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3742 }
3743
Willy Tarreau0f772532006-12-23 20:51:41 +01003744 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3745 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003746 chunk_destroy(&curproxy->errmsg[rc]);
3747 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003748 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003751
3752 if (rc >= HTTP_ERR_SIZE) {
3753 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3754 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 free(err);
3756 }
3757 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003758 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3759 int errnum, errlen, fd;
3760 char *err;
3761 struct stat stat;
3762
3763 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003765
3766 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003767 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003770 }
3771
3772 fd = open(args[2], O_RDONLY);
3773 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3774 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3775 file, linenum, args[2], args[1]);
3776 if (fd >= 0)
3777 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003780 }
3781
Willy Tarreau27a674e2009-08-17 07:23:33 +02003782 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003783 errlen = stat.st_size;
3784 } else {
3785 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003786 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003788 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003789 }
3790
3791 err = malloc(errlen); /* malloc() must succeed during parsing */
3792 errnum = read(fd, err, errlen);
3793 if (errnum != errlen) {
3794 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3795 file, linenum, args[2], args[1]);
3796 close(fd);
3797 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003800 }
3801 close(fd);
3802
3803 errnum = atol(args[1]);
3804 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3805 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003806 chunk_destroy(&curproxy->errmsg[rc]);
3807 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003808 break;
3809 }
3810 }
3811
3812 if (rc >= HTTP_ERR_SIZE) {
3813 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3814 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003816 free(err);
3817 }
3818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003820 struct cfg_kw_list *kwl;
3821 int index;
3822
3823 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3824 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3825 if (kwl->kw[index].section != CFG_LISTEN)
3826 continue;
3827 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3828 /* prepare error message just in case */
3829 snprintf(trash, sizeof(trash),
3830 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003831 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3832 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003833 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003836 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003837 else if (rc > 0) {
3838 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_WARN;
3840 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003841 }
Willy Tarreau93893792009-07-23 13:19:11 +02003842 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003843 }
3844 }
3845 }
3846
Willy Tarreau6daf3432008-01-22 16:44:08 +01003847 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
Willy Tarreau93893792009-07-23 13:19:11 +02003851 out:
3852 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853}
3854
3855
3856/*
3857 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003858 * Returns the error code, 0 if OK, or any combination of :
3859 * - ERR_ABORT: must abort ASAP
3860 * - ERR_FATAL: we can continue parsing but not start the service
3861 * - ERR_WARN: a warning has been emitted
3862 * - ERR_ALERT: an alert has been emitted
3863 * Only the two first ones can stop processing, the two others are just
3864 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003866int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003868 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 FILE *f;
3870 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003872 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 if ((f=fopen(file,"r")) == NULL)
3875 return -1;
3876
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003877 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003878 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003879 char *end;
3880 char *args[MAX_LINE_ARGS + 1];
3881 char *line = thisline;
3882
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 linenum++;
3884
3885 end = line + strlen(line);
3886
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003887 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3888 /* Check if we reached the limit and the last char is not \n.
3889 * Watch out for the last line without the terminating '\n'!
3890 */
3891 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003892 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003894 }
3895
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003897 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 line++;
3899
3900 arg = 0;
3901 args[arg] = line;
3902
3903 while (*line && arg < MAX_LINE_ARGS) {
3904 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3905 * C equivalent value. Other combinations left unchanged (eg: \1).
3906 */
3907 if (*line == '\\') {
3908 int skip = 0;
3909 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3910 *line = line[1];
3911 skip = 1;
3912 }
3913 else if (line[1] == 'r') {
3914 *line = '\r';
3915 skip = 1;
3916 }
3917 else if (line[1] == 'n') {
3918 *line = '\n';
3919 skip = 1;
3920 }
3921 else if (line[1] == 't') {
3922 *line = '\t';
3923 skip = 1;
3924 }
3925 else if (line[1] == 'x') {
3926 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3927 unsigned char hex1, hex2;
3928 hex1 = toupper(line[2]) - '0';
3929 hex2 = toupper(line[3]) - '0';
3930 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3931 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3932 *line = (hex1<<4) + hex2;
3933 skip = 3;
3934 }
3935 else {
3936 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 }
3939 }
3940 if (skip) {
3941 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3942 end -= skip;
3943 }
3944 line++;
3945 }
3946 else if (*line == '#' || *line == '\n' || *line == '\r') {
3947 /* end of string, end of loop */
3948 *line = 0;
3949 break;
3950 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003951 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003953 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003954 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 line++;
3956 args[++arg] = line;
3957 }
3958 else {
3959 line++;
3960 }
3961 }
3962
3963 /* empty line */
3964 if (!**args)
3965 continue;
3966
Willy Tarreau540abe42007-05-02 20:50:16 +02003967 /* zero out remaining args and ensure that at least one entry
3968 * is zeroed out.
3969 */
3970 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 args[arg] = line;
3972 }
3973
Willy Tarreau3842f002009-06-14 11:39:52 +02003974 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003975 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003976 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003977 for (arg=0; *args[arg+1]; arg++)
3978 args[arg] = args[arg+1]; // shift args after inversion
3979 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003980 else if (!strcmp(args[0], "default")) {
3981 kwm = KWM_DEF;
3982 for (arg=0; *args[arg+1]; arg++)
3983 args[arg] = args[arg+1]; // shift args after inversion
3984 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003985
Willy Tarreau3842f002009-06-14 11:39:52 +02003986 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3987 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003989 }
3990
Willy Tarreau977b8e42006-12-29 14:19:17 +01003991 if (!strcmp(args[0], "listen") ||
3992 !strcmp(args[0], "frontend") ||
3993 !strcmp(args[0], "backend") ||
3994 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003995 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003997 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003998 cursection = strdup(args[0]);
3999 }
4000 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004002 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004003 cursection = strdup(args[0]);
4004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 /* else it's a section keyword */
4006
4007 switch (confsect) {
4008 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 break;
4011 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004012 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 break;
4014 default:
4015 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004018
4019 if (err_code & ERR_ABORT)
4020 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004022 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004023 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004025 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004026}
4027
Willy Tarreaubb925012009-07-23 13:36:36 +02004028/*
4029 * Returns the error code, 0 if OK, or any combination of :
4030 * - ERR_ABORT: must abort ASAP
4031 * - ERR_FATAL: we can continue parsing but not start the service
4032 * - ERR_WARN: a warning has been emitted
4033 * - ERR_ALERT: an alert has been emitted
4034 * Only the two first ones can stop processing, the two others are just
4035 * indicators.
4036 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004037int check_config_validity()
4038{
4039 int cfgerr = 0;
4040 struct proxy *curproxy = NULL;
4041 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004042 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004043 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044
4045 /*
4046 * Now, check for the integrity of all that we have collected.
4047 */
4048
4049 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004050 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004052 /* first, we will invert the proxy list order */
4053 curproxy = NULL;
4054 while (proxy) {
4055 struct proxy *next;
4056
4057 next = proxy->next;
4058 proxy->next = curproxy;
4059 curproxy = proxy;
4060 if (!next)
4061 break;
4062 proxy = next;
4063 }
4064
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004066 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 }
4070
4071 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004072 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004073 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004074 unsigned int next_id;
4075
4076 if (!curproxy->uuid) {
4077 /* proxy ID not set, use automatic numbering with first
4078 * spare entry starting with next_pxid.
4079 */
4080 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4081 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4082 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4083 next_pxid++;
4084 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004085
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004087 /* ensure we don't keep listeners uselessly bound */
4088 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089 curproxy = curproxy->next;
4090 continue;
4091 }
4092
Willy Tarreauff01a212009-03-15 13:46:16 +01004093 switch (curproxy->mode) {
4094 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004095 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004096 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004097 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4098 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004099 cfgerr++;
4100 }
4101
4102 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004103 Warning("config : servers will be ignored for %s '%s'.\n",
4104 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004105 break;
4106
4107 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004108 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004109 break;
4110
4111 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004112 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004113 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004114 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4115 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004116 cfgerr++;
4117 }
4118 break;
4119 }
4120
4121 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004122 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4123 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004124 cfgerr++;
4125 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004126
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004127 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004128 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004129 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004130 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4131 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004132 cfgerr++;
4133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004135 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004136 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4137 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004138 cfgerr++;
4139 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004141 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004142 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4143 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004144 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004145 }
4146 }
4147 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4148 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4149 /* If no LB algo is set in a backend, and we're not in
4150 * transparent mode, dispatch mode nor proxy mode, we
4151 * want to use balance roundrobin by default.
4152 */
4153 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4154 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 }
4156 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004157
Willy Tarreau82936582007-11-30 15:20:09 +01004158 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4159 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004160 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4161 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004162 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004163 }
4164
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004165 /* if a default backend was specified, let's find it */
4166 if (curproxy->defbe.name) {
4167 struct proxy *target;
4168
Alex Williams96532db2009-11-01 21:27:13 -05004169 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004170 if (!target) {
4171 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4172 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004173 cfgerr++;
4174 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004175 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4176 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004177 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004178 } else {
4179 free(curproxy->defbe.name);
4180 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004181 /* we force the backend to be present on at least all of
4182 * the frontend's processes.
4183 */
4184 target->bind_proc = curproxy->bind_proc ?
4185 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 }
4187 }
4188
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004189 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004190 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4191 /* map jump target for ACT_SETBE in req_rep chain */
4192 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004193 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004194 struct proxy *target;
4195
Willy Tarreaua496b602006-12-17 23:15:24 +01004196 if (exp->action != ACT_SETBE)
4197 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004198
Alex Williams96532db2009-11-01 21:27:13 -05004199 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004200 if (!target) {
4201 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4202 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004203 cfgerr++;
4204 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004205 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4206 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004207 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004208 } else {
4209 free((void *)exp->replace);
4210 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004211 /* we force the backend to be present on at least all of
4212 * the frontend's processes.
4213 */
4214 target->bind_proc = curproxy->bind_proc ?
4215 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004216 }
4217 }
4218 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004219
4220 /* find the target proxy for 'use_backend' rules */
4221 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004222 struct proxy *target;
4223
Alex Williams96532db2009-11-01 21:27:13 -05004224 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004225
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004226 if (!target) {
4227 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4228 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004229 cfgerr++;
4230 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004231 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4232 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004233 cfgerr++;
4234 } else {
4235 free((void *)rule->be.name);
4236 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004237 /* we force the backend to be present on at least all of
4238 * the frontend's processes.
4239 */
4240 target->bind_proc = curproxy->bind_proc ?
4241 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004242 }
4243 }
4244
Willy Tarreau2738a142006-07-08 17:28:09 +02004245 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004246 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004247 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004248 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004249 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004250 " | While not properly invalid, you will certainly encounter various problems\n"
4251 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004252 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004253 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004254 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004255 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004256
Willy Tarreau1fa31262007-12-03 00:36:16 +01004257 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4258 * We must still support older configurations, so let's find out whether those
4259 * parameters have been set or must be copied from contimeouts.
4260 */
4261 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004262 if (!curproxy->timeout.tarpit ||
4263 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004264 /* tarpit timeout not set. We search in the following order:
4265 * default.tarpit, curr.connect, default.connect.
4266 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004267 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004268 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004269 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004270 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004271 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004272 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004273 }
4274 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004275 (!curproxy->timeout.queue ||
4276 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004277 /* queue timeout not set. We search in the following order:
4278 * default.queue, curr.connect, default.connect.
4279 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004280 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004281 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004282 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004283 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004284 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004285 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004286 }
4287 }
4288
Willy Tarreauf3c69202006-07-09 16:42:34 +02004289 if (curproxy->options & PR_O_SSL3_CHK) {
4290 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4291 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4292 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4293 }
4294
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004295 /* The small pools required for the capture lists */
4296 if (curproxy->nb_req_cap)
4297 curproxy->req_cap_pool = create_pool("ptrcap",
4298 curproxy->nb_req_cap * sizeof(char *),
4299 MEM_F_SHARED);
4300 if (curproxy->nb_rsp_cap)
4301 curproxy->rsp_cap_pool = create_pool("ptrcap",
4302 curproxy->nb_rsp_cap * sizeof(char *),
4303 MEM_F_SHARED);
4304
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004305 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4306 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4307 MEM_F_SHARED);
4308
Willy Tarreau86034312006-12-29 00:10:33 +01004309 /* for backwards compatibility with "listen" instances, if
4310 * fullconn is not set but maxconn is set, then maxconn
4311 * is used.
4312 */
4313 if (!curproxy->fullconn)
4314 curproxy->fullconn = curproxy->maxconn;
4315
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 /* first, we will invert the servers list order */
4317 newsrv = NULL;
4318 while (curproxy->srv) {
4319 struct server *next;
4320
4321 next = curproxy->srv->next;
4322 curproxy->srv->next = newsrv;
4323 newsrv = curproxy->srv;
4324 if (!next)
4325 break;
4326 curproxy->srv = next;
4327 }
4328
Willy Tarreau20697042007-11-15 23:26:18 +01004329 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004330 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004332 /* We have to initialize the server lookup mechanism depending
4333 * on what LB algorithm was choosen.
4334 */
4335
4336 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4337 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4338 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004339 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4340 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4341 init_server_map(curproxy);
4342 } else {
4343 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4344 fwrr_init_server_groups(curproxy);
4345 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004346 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004347
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004348 case BE_LB_KIND_LC:
4349 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004350 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004351 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004352
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004353 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004354 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4355 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4356 chash_init_server_tree(curproxy);
4357 } else {
4358 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4359 init_server_map(curproxy);
4360 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004361 break;
4362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363
4364 if (curproxy->options & PR_O_LOGASAP)
4365 curproxy->to_log &= ~LW_BYTES;
4366
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004367 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4368 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4369 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4370 proxy_type_str(curproxy), curproxy->id);
4371 err_code |= ERR_WARN;
4372 }
4373
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004375 * ensure that we're not cross-dressing a TCP server into HTTP.
4376 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004377 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004378 newsrv = curproxy->srv;
4379 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004380 if (!newsrv->puid) {
4381 /* server ID not set, use automatic numbering with first
4382 * spare entry starting with next_svid.
4383 */
4384 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4385 newsrv->conf.id.key = newsrv->puid = next_id;
4386 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4387 next_id++;
4388 }
4389
Willy Tarreau21d2af32008-02-14 20:25:24 +01004390 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004391 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4392 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004393 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004394 }
4395 newsrv = newsrv->next;
4396 }
4397
4398 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 * If this server supports a maxconn parameter, it needs a dedicated
4400 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004401 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 */
4403 newsrv = curproxy->srv;
4404 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004405 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004406 /* Only 'minconn' was specified, or it was higher than or equal
4407 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4408 * this will avoid further useless expensive computations.
4409 */
4410 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004411 } else if (newsrv->maxconn && !newsrv->minconn) {
4412 /* minconn was not specified, so we set it to maxconn */
4413 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004414 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004415 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4416 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004417 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 }
4419
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004420 if (newsrv->trackit) {
4421 struct proxy *px;
4422 struct server *srv;
4423 char *pname, *sname;
4424
4425 pname = newsrv->trackit;
4426 sname = strrchr(pname, '/');
4427
4428 if (sname)
4429 *sname++ = '\0';
4430 else {
4431 sname = pname;
4432 pname = NULL;
4433 }
4434
4435 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004436 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004437 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004438 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4439 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004440 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004441 cfgerr++;
4442 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004443 }
4444 } else
4445 px = curproxy;
4446
4447 srv = findserver(px, sname);
4448 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004449 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4450 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004451 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004452 cfgerr++;
4453 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004454 }
4455
4456 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004457 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004458 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004459 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004460 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004461 cfgerr++;
4462 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004463 }
4464
4465 if (curproxy != px &&
4466 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004467 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004468 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004469 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004470 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004471 cfgerr++;
4472 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004473 }
4474
4475 newsrv->tracked = srv;
4476 newsrv->tracknext = srv->tracknext;
4477 srv->tracknext = newsrv;
4478
4479 free(newsrv->trackit);
4480 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004481 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 newsrv = newsrv->next;
4483 }
4484
Willy Tarreauc1a21672009-08-16 22:37:44 +02004485 if (curproxy->cap & PR_CAP_FE) {
4486 if (curproxy->tcp_req.inspect_delay ||
4487 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4488 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4489
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004490 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004491 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004492 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004493 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004494
4495 /* both TCP and HTTP must check switching rules */
4496 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4497 }
4498
4499 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004500 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004501 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004502 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004503 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004504
4505 /* If the backend does requires RDP cookie persistence, we have to
4506 * enable the corresponding analyser.
4507 */
4508 if (curproxy->options2 & PR_O2_RDPC_PRST)
4509 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4510 }
4511
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004512 listener = NULL;
4513 while (curproxy->listen) {
4514 struct listener *next;
4515
4516 next = curproxy->listen->next;
4517 curproxy->listen->next = listener;
4518 listener = curproxy->listen;
4519
4520 if (!next)
4521 break;
4522
4523 curproxy->listen = next;
4524 }
4525
Willy Tarreaue6b98942007-10-29 01:09:36 +01004526 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004527 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004528 listener = curproxy->listen;
4529 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004530 if (!listener->luid) {
4531 /* listener ID not set, use automatic numbering with first
4532 * spare entry starting with next_luid.
4533 */
4534 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4535 listener->conf.id.key = listener->luid = next_id;
4536 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4537 next_id++;
4538 }
4539
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004540 /* enable separate counters */
4541 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4542 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4543 if (!listener->name) {
4544 sprintf(trash, "sock-%d", listener->luid);
4545 listener->name = strdup(trash);
4546 }
4547 }
4548
Willy Tarreaue6b98942007-10-29 01:09:36 +01004549 if (curproxy->options & PR_O_TCP_NOLING)
4550 listener->options |= LI_O_NOLINGER;
4551 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004552 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004553 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004554 listener->accept = event_accept;
4555 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004556 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004557 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004558
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004559 /* smart accept mode is automatic in HTTP mode */
4560 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4561 (curproxy->mode == PR_MODE_HTTP &&
4562 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4563 listener->options |= LI_O_NOQUICKACK;
4564
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004565 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004566 listener = listener->next;
4567 }
4568
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 curproxy = curproxy->next;
4570 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004571
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004572 /*
4573 * Recount currently required checks.
4574 */
4575
4576 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4577 int optnum;
4578
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004579 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4580 if (curproxy->options & cfg_opts[optnum].val)
4581 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004582
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004583 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4584 if (curproxy->options2 & cfg_opts2[optnum].val)
4585 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004586 }
4587
Willy Tarreaubb925012009-07-23 13:36:36 +02004588 if (cfgerr > 0)
4589 err_code |= ERR_ALERT | ERR_FATAL;
4590 out:
4591 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592}
4593
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004594/*
4595 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4596 * parsing sessions.
4597 */
4598void cfg_register_keywords(struct cfg_kw_list *kwl)
4599{
4600 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4601}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004603/*
4604 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4605 */
4606void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4607{
4608 LIST_DEL(&kwl->list);
4609 LIST_INIT(&kwl->list);
4610}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611
4612/*
4613 * Local variables:
4614 * c-indent-level: 8
4615 * c-basic-offset: 8
4616 * End:
4617 */