blob: fd5c626e3deecc16cd0d5c21690ce4c2f1a0058e [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 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538
Willy Tarreau977b8e42006-12-29 14:19:17 +01001539 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001540 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001541
Willy Tarreaubaaee002006-06-26 02:48:02 +02001542 if (*(args[5]) == 0) {
1543 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1544 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 }
1548 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001549 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 curproxy->appsession_name = strdup(args[1]);
1551 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1552 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001553 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1554 if (err) {
1555 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1556 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001557 err_code |= ERR_ALERT | ERR_FATAL;
1558 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001559 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001560 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001561
Willy Tarreau51041c72007-09-09 21:56:53 +02001562 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1563 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001564 err_code |= ERR_ALERT | ERR_ABORT;
1565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 }
1567 } /* Url App Session */
1568 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001571
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 if (*(args[4]) == 0) {
1574 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001579 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 curproxy->capture_name = strdup(args[2]);
1581 curproxy->capture_namelen = strlen(curproxy->capture_name);
1582 curproxy->capture_len = atol(args[4]);
1583 if (curproxy->capture_len >= CAPTURE_LEN) {
1584 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1585 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001586 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 curproxy->capture_len = CAPTURE_LEN - 1;
1588 }
1589 curproxy->to_log |= LW_COOKIE;
1590 }
1591 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1592 struct cap_hdr *hdr;
1593
1594 if (curproxy == &defproxy) {
1595 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 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 }
1599
1600 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1601 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1602 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
1604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
1606
1607 hdr = calloc(sizeof(struct cap_hdr), 1);
1608 hdr->next = curproxy->req_cap;
1609 hdr->name = strdup(args[3]);
1610 hdr->namelen = strlen(args[3]);
1611 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001612 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 hdr->index = curproxy->nb_req_cap++;
1614 curproxy->req_cap = hdr;
1615 curproxy->to_log |= LW_REQHDR;
1616 }
1617 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1618 struct cap_hdr *hdr;
1619
1620 if (curproxy == &defproxy) {
1621 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 +02001622 err_code |= ERR_ALERT | ERR_FATAL;
1623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 }
1625
1626 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1627 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1628 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 }
1632 hdr = calloc(sizeof(struct cap_hdr), 1);
1633 hdr->next = curproxy->rsp_cap;
1634 hdr->name = strdup(args[3]);
1635 hdr->namelen = strlen(args[3]);
1636 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001637 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 hdr->index = curproxy->nb_rsp_cap++;
1639 curproxy->rsp_cap = hdr;
1640 curproxy->to_log |= LW_RSPHDR;
1641 }
1642 else {
1643 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 }
1648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001650 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001652
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 if (*(args[1]) == 0) {
1654 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1655 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 }
1659 curproxy->conn_retries = atol(args[1]);
1660 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001661 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1662 int pol = ACL_COND_NONE;
1663 struct acl_cond *cond;
1664
Willy Tarreaub099aca2008-10-12 17:26:37 +02001665 if (curproxy == &defproxy) {
1666 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001669 }
1670
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001671 if (!strcmp(args[1], "if"))
1672 pol = ACL_COND_IF;
1673 else if (!strcmp(args[1], "unless"))
1674 pol = ACL_COND_UNLESS;
1675
1676 if (pol == ACL_COND_NONE) {
1677 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1678 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001679 err_code |= ERR_ALERT | ERR_FATAL;
1680 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001681 }
1682
1683 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1684 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1685 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001688 }
Willy Tarreau88922352009-10-04 22:02:50 +02001689 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001690 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001691 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001692 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001693 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001694 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001695 else if (!strcmp(args[0], "redirect")) {
1696 int pol = ACL_COND_NONE;
1697 struct acl_cond *cond;
1698 struct redirect_rule *rule;
1699 int cur_arg;
1700 int type = REDIRECT_TYPE_NONE;
1701 int code = 302;
1702 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001703 char *cookie = NULL;
1704 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001705 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001706
1707 cur_arg = 1;
1708 while (*(args[cur_arg])) {
1709 if (!strcmp(args[cur_arg], "location")) {
1710 if (!*args[cur_arg + 1]) {
1711 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1712 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001713 err_code |= ERR_ALERT | ERR_FATAL;
1714 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001715 }
1716
1717 type = REDIRECT_TYPE_LOCATION;
1718 cur_arg++;
1719 destination = args[cur_arg];
1720 }
1721 else if (!strcmp(args[cur_arg], "prefix")) {
1722 if (!*args[cur_arg + 1]) {
1723 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1724 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
1726 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001727 }
1728
1729 type = REDIRECT_TYPE_PREFIX;
1730 cur_arg++;
1731 destination = args[cur_arg];
1732 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001733 else if (!strcmp(args[cur_arg], "set-cookie")) {
1734 if (!*args[cur_arg + 1]) {
1735 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1736 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001739 }
1740
1741 cur_arg++;
1742 cookie = args[cur_arg];
1743 cookie_set = 1;
1744 }
1745 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1746 if (!*args[cur_arg + 1]) {
1747 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1748 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001751 }
1752
1753 cur_arg++;
1754 cookie = args[cur_arg];
1755 cookie_set = 0;
1756 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001757 else if (!strcmp(args[cur_arg],"code")) {
1758 if (!*args[cur_arg + 1]) {
1759 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1760 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001763 }
1764 cur_arg++;
1765 code = atol(args[cur_arg]);
1766 if (code < 301 || code > 303) {
1767 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1768 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001771 }
1772 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001773 else if (!strcmp(args[cur_arg],"drop-query")) {
1774 flags |= REDIRECT_FLAG_DROP_QS;
1775 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001776 else if (!strcmp(args[cur_arg], "if")) {
1777 pol = ACL_COND_IF;
1778 cur_arg++;
1779 break;
1780 }
1781 else if (!strcmp(args[cur_arg], "unless")) {
1782 pol = ACL_COND_UNLESS;
1783 cur_arg++;
1784 break;
1785 }
1786 else {
1787 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1788 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001791 }
1792 cur_arg++;
1793 }
1794
1795 if (type == REDIRECT_TYPE_NONE) {
1796 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1797 file, linenum, args[0]);
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
1802 if (pol == ACL_COND_NONE) {
1803 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1804 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001807 }
1808
1809 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001810 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001811 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001814 }
1815
Willy Tarreau88922352009-10-04 22:02:50 +02001816 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001817 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001818 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001819 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1820 rule->cond = cond;
1821 rule->rdr_str = strdup(destination);
1822 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001823 if (cookie) {
1824 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1825 * a clear consists in appending "; Max-Age=0" at the end.
1826 */
1827 rule->cookie_len = strlen(cookie);
1828 if (cookie_set)
1829 rule->cookie_str = strdup(cookie);
1830 else {
1831 rule->cookie_str = malloc(rule->cookie_len + 12);
1832 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1833 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1834 rule->cookie_len += 11;
1835 }
1836 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001837 rule->type = type;
1838 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001839 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001840 LIST_INIT(&rule->list);
1841 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001842 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001843 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001844 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001845 int pol = ACL_COND_NONE;
1846 struct acl_cond *cond;
1847 struct switching_rule *rule;
1848
Willy Tarreaub099aca2008-10-12 17:26:37 +02001849 if (curproxy == &defproxy) {
1850 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001853 }
1854
Willy Tarreau55ea7572007-06-17 19:56:27 +02001855 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001857
1858 if (*(args[1]) == 0) {
1859 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001862 }
1863
1864 if (!strcmp(args[2], "if"))
1865 pol = ACL_COND_IF;
1866 else if (!strcmp(args[2], "unless"))
1867 pol = ACL_COND_UNLESS;
1868
1869 if (pol == ACL_COND_NONE) {
1870 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1871 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001872 err_code |= ERR_ALERT | ERR_FATAL;
1873 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001874 }
1875
1876 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001877 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001878 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001879 err_code |= ERR_ALERT | ERR_FATAL;
1880 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001881 }
1882
Willy Tarreau88922352009-10-04 22:02:50 +02001883 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001884 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001885 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001886 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001887 struct acl *acl;
1888 const char *name;
1889
1890 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1891 name = acl ? acl->name : "(unknown)";
1892 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1893 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001894 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001895 }
1896
Willy Tarreau55ea7572007-06-17 19:56:27 +02001897 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1898 rule->cond = cond;
1899 rule->be.name = strdup(args[1]);
1900 LIST_INIT(&rule->list);
1901 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001905 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001906
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1908 curproxy->uri_auth = NULL; /* we must detach from the default config */
1909
1910 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001911 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 +02001912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 } else if (!strcmp(args[1], "uri")) {
1915 if (*(args[2]) == 0) {
1916 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001917 err_code |= ERR_ALERT | ERR_FATAL;
1918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1920 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_ABORT;
1922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 }
1924 } else if (!strcmp(args[1], "realm")) {
1925 if (*(args[2]) == 0) {
1926 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1930 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_ABORT;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001934 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001935 unsigned interval;
1936
1937 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1938 if (err) {
1939 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1940 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001943 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1944 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001945 err_code |= ERR_ALERT | ERR_ABORT;
1946 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948 } else if (!strcmp(args[1], "auth")) {
1949 if (*(args[2]) == 0) {
1950 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_ALERT | ERR_FATAL;
1952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1954 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001955 err_code |= ERR_ALERT | ERR_ABORT;
1956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 }
1958 } else if (!strcmp(args[1], "scope")) {
1959 if (*(args[2]) == 0) {
1960 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1964 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_ABORT;
1966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 }
1968 } else if (!strcmp(args[1], "enable")) {
1969 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1970 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001971 err_code |= ERR_ALERT | ERR_ABORT;
1972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001974 } else if (!strcmp(args[1], "hide-version")) {
1975 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1976 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001977 err_code |= ERR_ALERT | ERR_ABORT;
1978 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001979 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001980 } else if (!strcmp(args[1], "show-node")) {
1981
1982 if (*args[2]) {
1983 int i;
1984 char c;
1985
1986 for (i=0; args[2][i]; i++) {
1987 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02001988 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001989 break;
1990 }
1991
1992 if (!i || args[2][i]) {
1993 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1994 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1995 file, linenum, args[0], args[1]);
1996 err_code |= ERR_ALERT | ERR_FATAL;
1997 goto out;
1998 }
1999 }
2000
2001 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2002 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2003 err_code |= ERR_ALERT | ERR_ABORT;
2004 goto out;
2005 }
2006 } else if (!strcmp(args[1], "show-desc")) {
2007 char *desc = NULL;
2008
2009 if (*args[2]) {
2010 int i, len=0;
2011 char *d;
2012
2013 for(i=2; *args[i]; i++)
2014 len += strlen(args[i])+1;
2015
2016 desc = d = (char *)calloc(1, len);
2017
2018 d += sprintf(d, "%s", args[2]);
2019 for(i=3; *args[i]; i++)
2020 d += sprintf(d, " %s", args[i]);
2021 }
2022
2023 if (!*args[2] && !global.desc)
2024 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2025 file, linenum, args[1]);
2026 else {
2027 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2028 free(desc);
2029 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2030 err_code |= ERR_ALERT | ERR_ABORT;
2031 goto out;
2032 }
2033 free(desc);
2034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002036 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 }
2041 }
2042 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002043 int optnum;
2044
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002045 if (*(args[1]) == '\0') {
2046 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002051
2052 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2053 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002054 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2055 err_code |= ERR_WARN;
2056 goto out;
2057 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002058
Willy Tarreau3842f002009-06-14 11:39:52 +02002059 curproxy->no_options &= ~cfg_opts[optnum].val;
2060 curproxy->options &= ~cfg_opts[optnum].val;
2061
2062 switch (kwm) {
2063 case KWM_STD:
2064 curproxy->options |= cfg_opts[optnum].val;
2065 break;
2066 case KWM_NO:
2067 curproxy->no_options |= cfg_opts[optnum].val;
2068 break;
2069 case KWM_DEF: /* already cleared */
2070 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002071 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002072
Willy Tarreau93893792009-07-23 13:19:11 +02002073 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002074 }
2075 }
2076
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002077 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2078 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002079 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2080 err_code |= ERR_WARN;
2081 goto out;
2082 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002083
Willy Tarreau3842f002009-06-14 11:39:52 +02002084 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2085 curproxy->options2 &= ~cfg_opts2[optnum].val;
2086
2087 switch (kwm) {
2088 case KWM_STD:
2089 curproxy->options2 |= cfg_opts2[optnum].val;
2090 break;
2091 case KWM_NO:
2092 curproxy->no_options2 |= cfg_opts2[optnum].val;
2093 break;
2094 case KWM_DEF: /* already cleared */
2095 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002096 }
Willy Tarreau93893792009-07-23 13:19:11 +02002097 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002098 }
2099 }
2100
Willy Tarreau3842f002009-06-14 11:39:52 +02002101 if (kwm != KWM_STD) {
2102 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002103 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002106 }
2107
Emeric Brun3a058f32009-06-30 18:26:00 +02002108 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002110 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002112 if (*(args[2]) != '\0') {
2113 if (!strcmp(args[2], "clf")) {
2114 curproxy->options2 |= PR_O2_CLFLOG;
2115 } else {
2116 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002119 }
2120 }
2121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 else if (!strcmp(args[1], "tcplog"))
2123 /* generate a detailed TCP log */
2124 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 else if (!strcmp(args[1], "tcpka")) {
2126 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002127 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002128 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002129
2130 if (curproxy->cap & PR_CAP_FE)
2131 curproxy->options |= PR_O_TCP_CLI_KA;
2132 if (curproxy->cap & PR_CAP_BE)
2133 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 }
2135 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_WARN;
2138
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002140 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002141 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002142 curproxy->options &= ~PR_O_SMTP_CHK;
2143 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 if (!*args[2]) { /* no argument */
2145 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2146 curproxy->check_len = strlen(DEF_CHECK_REQ);
2147 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002148 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149 curproxy->check_req = (char *)malloc(reqlen);
2150 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2151 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2152 } else { /* more arguments : METHOD URI [HTTP_VER] */
2153 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2154 if (*args[4])
2155 reqlen += strlen(args[4]);
2156 else
2157 reqlen += strlen("HTTP/1.0");
2158
2159 curproxy->check_req = (char *)malloc(reqlen);
2160 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2161 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2162 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002163 }
2164 else if (!strcmp(args[1], "ssl-hello-chk")) {
2165 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002166 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002167 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002168
Willy Tarreaua534fea2008-08-03 12:19:50 +02002169 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002170 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002171 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002172 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 }
Willy Tarreau23677902007-05-08 23:50:35 +02002174 else if (!strcmp(args[1], "smtpchk")) {
2175 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002176 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002177 curproxy->options &= ~PR_O_HTTP_CHK;
2178 curproxy->options &= ~PR_O_SSL3_CHK;
2179 curproxy->options |= PR_O_SMTP_CHK;
2180
2181 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2182 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2183 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2184 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2185 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2186 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2187 curproxy->check_req = (char *)malloc(reqlen);
2188 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2189 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2190 } else {
2191 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2192 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2193 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2194 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2195 }
2196 }
2197 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002198 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002199 int cur_arg;
2200
2201 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2202 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002203 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002204
2205 curproxy->options |= PR_O_FWDFOR;
2206
2207 free(curproxy->fwdfor_hdr_name);
2208 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2209 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2210
2211 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2212 cur_arg = 2;
2213 while (*(args[cur_arg])) {
2214 if (!strcmp(args[cur_arg], "except")) {
2215 /* suboption except - needs additional argument for it */
2216 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2217 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2218 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002221 }
2222 /* flush useless bits */
2223 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002224 cur_arg += 2;
2225 } else if (!strcmp(args[cur_arg], "header")) {
2226 /* suboption header - needs additional argument for it */
2227 if (*(args[cur_arg+1]) == 0) {
2228 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2229 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002232 }
2233 free(curproxy->fwdfor_hdr_name);
2234 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2235 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2236 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002237 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002238 /* unknown suboption - catchall */
2239 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2240 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002243 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002244 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002245 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002246 else if (!strcmp(args[1], "originalto")) {
2247 int cur_arg;
2248
2249 /* insert x-original-to field, but not for the IP address listed as an except.
2250 * set default options (ie: bitfield, header name, etc)
2251 */
2252
2253 curproxy->options |= PR_O_ORGTO;
2254
2255 free(curproxy->orgto_hdr_name);
2256 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2257 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2258
2259 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2260 cur_arg = 2;
2261 while (*(args[cur_arg])) {
2262 if (!strcmp(args[cur_arg], "except")) {
2263 /* suboption except - needs additional argument for it */
2264 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2265 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2266 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002269 }
2270 /* flush useless bits */
2271 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2272 cur_arg += 2;
2273 } else if (!strcmp(args[cur_arg], "header")) {
2274 /* suboption header - needs additional argument for it */
2275 if (*(args[cur_arg+1]) == 0) {
2276 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2277 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002280 }
2281 free(curproxy->orgto_hdr_name);
2282 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2283 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2284 cur_arg += 2;
2285 } else {
2286 /* unknown suboption - catchall */
2287 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2288 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002291 }
2292 } /* end while loop */
2293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 else {
2295 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 }
Willy Tarreau93893792009-07-23 13:19:11 +02002299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002301 else if (!strcmp(args[0], "default_backend")) {
2302 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002304
2305 if (*(args[1]) == 0) {
2306 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002309 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002310 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002311 curproxy->defbe.name = strdup(args[1]);
2312 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002314 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002316
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002317 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2318 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002319 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 /* enable reconnections to dispatch */
2321 curproxy->options |= PR_O_REDISP;
2322 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002323 else if (!strcmp(args[0], "http-check")) {
2324 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002326
2327 if (strcmp(args[1], "disable-on-404") == 0) {
2328 /* enable a graceful server shutdown on an HTTP 404 response */
2329 curproxy->options |= PR_O_DISABLE404;
2330 }
2331 else {
2332 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002335 }
2336 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002337 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002338 if (curproxy == &defproxy) {
2339 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002342 }
2343
Willy Tarreaub80c2302007-11-30 20:51:32 +01002344 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002346
2347 if (strcmp(args[1], "fail") == 0) {
2348 /* add a condition to fail monitor requests */
2349 int pol = ACL_COND_NONE;
2350 struct acl_cond *cond;
2351
2352 if (!strcmp(args[2], "if"))
2353 pol = ACL_COND_IF;
2354 else if (!strcmp(args[2], "unless"))
2355 pol = ACL_COND_UNLESS;
2356
2357 if (pol == ACL_COND_NONE) {
2358 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2359 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002362 }
2363
2364 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2365 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2366 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002369 }
Willy Tarreau88922352009-10-04 22:02:50 +02002370 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002371 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002372 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002373 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2374 }
2375 else {
2376 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002379 }
2380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381#ifdef TPROXY
2382 else if (!strcmp(args[0], "transparent")) {
2383 /* enable transparent proxy connections */
2384 curproxy->options |= PR_O_TRANSP;
2385 }
2386#endif
2387 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002388 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002389 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 if (*(args[1]) == 0) {
2392 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396 curproxy->maxconn = atol(args[1]);
2397 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002398 else if (!strcmp(args[0], "backlog")) { /* backlog */
2399 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002401
2402 if (*(args[1]) == 0) {
2403 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002406 }
2407 curproxy->backlog = atol(args[1]);
2408 }
Willy Tarreau86034312006-12-29 00:10:33 +01002409 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002410 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002412
Willy Tarreau86034312006-12-29 00:10:33 +01002413 if (*(args[1]) == 0) {
2414 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002417 }
2418 curproxy->fullconn = atol(args[1]);
2419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2421 if (*(args[1]) == 0) {
2422 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002426 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2427 if (err) {
2428 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2429 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002432 }
2433 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2436 if (curproxy == &defproxy) {
2437 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002441 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002443
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 if (strchr(args[1], ':') == NULL) {
2445 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
2449 curproxy->dispatch_addr = *str2sa(args[1]);
2450 }
2451 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002452 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002454
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002455 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002456 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2457 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002462 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2463 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2464 err_code |= ERR_WARN;
2465
2466 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2467 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2468 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2469 }
2470 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2471 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2472 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2473 }
2474 else {
2475 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 else if (!strcmp(args[0], "server")) { /* server address */
2481 int cur_arg;
2482 char *rport;
2483 char *raddr;
2484 short realport;
2485 int do_check;
2486
2487 if (curproxy == &defproxy) {
2488 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002492 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494
2495 if (!*args[2]) {
2496 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2497 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 Tarreau2e74c3f2007-12-02 18:45:09 +01002501
2502 err = invalid_char(args[1]);
2503 if (err) {
2504 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2505 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002508 }
2509
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2511 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002512 err_code |= ERR_ALERT | ERR_ABORT;
2513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 }
2515
2516 /* the servers are linked backwards first */
2517 newsrv->next = curproxy->srv;
2518 curproxy->srv = newsrv;
2519 newsrv->proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002520 newsrv->conf.file = file;
2521 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522
2523 LIST_INIT(&newsrv->pendconns);
2524 do_check = 0;
2525 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002526 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 newsrv->id = strdup(args[1]);
2528
2529 /* several ways to check the port component :
2530 * - IP => port=+0, relative
2531 * - IP: => port=+0, relative
2532 * - IP:N => port=N, absolute
2533 * - IP:+N => port=+N, relative
2534 * - IP:-N => port=-N, relative
2535 */
2536 raddr = strdup(args[2]);
2537 rport = strchr(raddr, ':');
2538 if (rport) {
2539 *rport++ = 0;
2540 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002541 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 newsrv->state |= SRV_MAPPORTS;
2543 } else {
2544 realport = 0;
2545 newsrv->state |= SRV_MAPPORTS;
2546 }
2547
2548 newsrv->addr = *str2sa(raddr);
2549 newsrv->addr.sin_port = htons(realport);
2550 free(raddr);
2551
2552 newsrv->curfd = -1; /* no health-check in progress */
2553 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002554 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2555 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 newsrv->rise = DEF_RISETIME;
2557 newsrv->fall = DEF_FALLTIME;
2558 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau975c50b2009-10-10 19:34:06 +02002559 newsrv->uweight = newsrv->iweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002560 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002561 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002562
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 cur_arg = 3;
2564 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002565 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002566 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002567
2568 if (!*args[cur_arg + 1]) {
2569 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2570 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002573 }
2574
2575 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002576 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002577
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002578 if (newsrv->puid <= 0) {
2579 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002580 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002583 }
2584
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002585 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2586 if (node) {
2587 struct server *target = container_of(node, struct server, conf.id);
2588 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2589 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
2592 }
2593 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002594 cur_arg += 2;
2595 }
2596 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 newsrv->cookie = strdup(args[cur_arg + 1]);
2598 newsrv->cklen = strlen(args[cur_arg + 1]);
2599 cur_arg += 2;
2600 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002601 else if (!strcmp(args[cur_arg], "redir")) {
2602 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2603 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2604 cur_arg += 2;
2605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002607 if (!*args[cur_arg + 1]) {
2608 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2609 file, linenum, args[cur_arg]);
2610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
2612 }
2613
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002615 if (newsrv->rise <= 0) {
2616 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2617 file, linenum, args[cur_arg]);
2618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
2620 }
2621
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 newsrv->health = newsrv->rise;
2623 cur_arg += 2;
2624 }
2625 else if (!strcmp(args[cur_arg], "fall")) {
2626 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002627
2628 if (!*args[cur_arg + 1]) {
2629 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2630 file, linenum, args[cur_arg]);
2631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
2633 }
2634
2635 if (newsrv->fall <= 0) {
2636 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2637 file, linenum, args[cur_arg]);
2638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
2641
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 cur_arg += 2;
2643 }
2644 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002645 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2646 if (err) {
2647 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2648 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002651 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002652 if (val <= 0) {
2653 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2654 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002657 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002658 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659 cur_arg += 2;
2660 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002661 else if (!strcmp(args[cur_arg], "fastinter")) {
2662 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2663 if (err) {
2664 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2665 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002668 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002669 if (val <= 0) {
2670 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2671 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002674 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002675 newsrv->fastinter = val;
2676 cur_arg += 2;
2677 }
2678 else if (!strcmp(args[cur_arg], "downinter")) {
2679 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2680 if (err) {
2681 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2682 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002685 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002686 if (val <= 0) {
2687 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2688 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002691 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002692 newsrv->downinter = val;
2693 cur_arg += 2;
2694 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002695 else if (!strcmp(args[cur_arg], "addr")) {
2696 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002697 cur_arg += 2;
2698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 else if (!strcmp(args[cur_arg], "port")) {
2700 newsrv->check_port = atol(args[cur_arg + 1]);
2701 cur_arg += 2;
2702 }
2703 else if (!strcmp(args[cur_arg], "backup")) {
2704 newsrv->state |= SRV_BACKUP;
2705 cur_arg ++;
2706 }
2707 else if (!strcmp(args[cur_arg], "weight")) {
2708 int w;
2709 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002710 if (w < 0 || w > 256) {
2711 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002716 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 cur_arg += 2;
2718 }
2719 else if (!strcmp(args[cur_arg], "minconn")) {
2720 newsrv->minconn = atol(args[cur_arg + 1]);
2721 cur_arg += 2;
2722 }
2723 else if (!strcmp(args[cur_arg], "maxconn")) {
2724 newsrv->maxconn = atol(args[cur_arg + 1]);
2725 cur_arg += 2;
2726 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002727 else if (!strcmp(args[cur_arg], "maxqueue")) {
2728 newsrv->maxqueue = atol(args[cur_arg + 1]);
2729 cur_arg += 2;
2730 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002731 else if (!strcmp(args[cur_arg], "slowstart")) {
2732 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002733 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002734 if (err) {
2735 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2736 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002739 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002740 if (val <= 0) {
2741 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2742 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002745 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002746 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002747 cur_arg += 2;
2748 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002749 else if (!strcmp(args[cur_arg], "track")) {
2750
2751 if (!*args[cur_arg + 1]) {
2752 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2753 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002756 }
2757
2758 newsrv->trackit = strdup(args[cur_arg + 1]);
2759
2760 cur_arg += 2;
2761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 else if (!strcmp(args[cur_arg], "check")) {
2763 global.maxsock++;
2764 do_check = 1;
2765 cur_arg += 1;
2766 }
2767 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002768 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002770#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002771 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002772 file, linenum, "source", "usesrc");
2773#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002774 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002776#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 }
2780 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002781 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2782
2783 if (port_low != port_high) {
2784 int i;
2785 if (port_low <= 0 || port_low > 65535 ||
2786 port_high <= 0 || port_high > 65535 ||
2787 port_low > port_high) {
2788 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2789 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002792 }
2793 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2794 for (i = 0; i < newsrv->sport_range->size; i++)
2795 newsrv->sport_range->ports[i] = port_low + i;
2796 }
2797
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002799 while (*(args[cur_arg])) {
2800 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002801#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2802#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002803 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2804 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2805 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002808 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002809#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002810 if (!*args[cur_arg + 1]) {
2811 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2812 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002815 }
2816 if (!strcmp(args[cur_arg + 1], "client")) {
2817 newsrv->state |= SRV_TPROXY_CLI;
2818 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2819 newsrv->state |= SRV_TPROXY_CIP;
2820 } else {
2821 newsrv->state |= SRV_TPROXY_ADDR;
2822 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2823 }
2824 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002825#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002826 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002827#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002828 cur_arg += 2;
2829 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002830#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002831 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002832 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002835#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2836 } /* "usesrc" */
2837
2838 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2839#ifdef SO_BINDTODEVICE
2840 if (!*args[cur_arg + 1]) {
2841 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2842 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002845 }
2846 if (newsrv->iface_name)
2847 free(newsrv->iface_name);
2848
2849 newsrv->iface_name = strdup(args[cur_arg + 1]);
2850 newsrv->iface_len = strlen(newsrv->iface_name);
2851 global.last_checks |= LSTCHK_NETADM;
2852#else
2853 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2854 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002857#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002858 cur_arg += 2;
2859 continue;
2860 }
2861 /* this keyword in not an option of "source" */
2862 break;
2863 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002865 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2866 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2867 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002872 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 +02002873 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 }
2877 }
2878
2879 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002880 if (newsrv->trackit) {
2881 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2882 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002885 }
2886
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002887 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2888 newsrv->check_port = newsrv->check_addr.sin_port;
2889
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2891 newsrv->check_port = realport; /* by default */
2892 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002893 /* not yet valid, because no port was set on
2894 * the server either. We'll check if we have
2895 * a known port on the first listener.
2896 */
2897 struct listener *l;
2898 l = curproxy->listen;
2899 if (l) {
2900 int port;
2901 port = (l->addr.ss_family == AF_INET6)
2902 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2903 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2904 newsrv->check_port = port;
2905 }
2906 }
2907 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2909 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02002913
2914 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 newsrv->state |= SRV_CHECKED;
2916 }
2917
2918 if (newsrv->state & SRV_BACKUP)
2919 curproxy->srv_bck++;
2920 else
2921 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002922
2923 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 }
2925 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002926 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 int facility;
2928
2929 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2930 curproxy->logfac1 = global.logfac1;
2931 curproxy->logsrv1 = global.logsrv1;
2932 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002933 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 curproxy->logfac2 = global.logfac2;
2935 curproxy->logsrv2 = global.logsrv2;
2936 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002937 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 }
2939 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002940 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941
2942 facility = get_log_facility(args[2]);
2943 if (facility < 0) {
2944 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2945 exit(1);
2946 }
2947
2948 level = 7; /* max syslog level = debug */
2949 if (*(args[3])) {
2950 level = get_log_level(args[3]);
2951 if (level < 0) {
2952 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2953 exit(1);
2954 }
2955 }
2956
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002957 minlvl = 0; /* limit syslog level to this level (emerg) */
2958 if (*(args[4])) {
2959 minlvl = get_log_level(args[4]);
2960 if (level < 0) {
2961 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2962 exit(1);
2963 }
2964 }
2965
Robert Tsai81ae1952007-12-05 10:47:29 +01002966 if (args[1][0] == '/') {
2967 logsrv.u.addr.sa_family = AF_UNIX;
2968 logsrv.u.un = *str2sun(args[1]);
2969 } else {
2970 logsrv.u.addr.sa_family = AF_INET;
2971 logsrv.u.in = *str2sa(args[1]);
2972 if (!logsrv.u.in.sin_port) {
2973 logsrv.u.in.sin_port =
2974 htons(SYSLOG_PORT);
2975 }
2976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977
2978 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002979 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 curproxy->logfac1 = facility;
2981 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002982 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002983 }
2984 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002985 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002986 curproxy->logfac2 = facility;
2987 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002988 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 }
2990 else {
2991 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 }
2995 }
2996 else {
2997 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2998 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 }
3002 }
3003 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003004 int cur_arg;
3005
Willy Tarreau977b8e42006-12-29 14:19:17 +01003006 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003010 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3011 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003015
3016 /* we must first clear any optional default setting */
3017 curproxy->options &= ~PR_O_TPXY_MASK;
3018 free(curproxy->iface_name);
3019 curproxy->iface_name = NULL;
3020 curproxy->iface_len = 0;
3021
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 curproxy->source_addr = *str2sa(args[1]);
3023 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003024
3025 cur_arg = 2;
3026 while (*(args[cur_arg])) {
3027 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003028#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3029#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003030 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3031 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3032 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003035 }
3036#endif
3037 if (!*args[cur_arg + 1]) {
3038 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3039 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003042 }
3043
3044 if (!strcmp(args[cur_arg + 1], "client")) {
3045 curproxy->options |= PR_O_TPXY_CLI;
3046 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3047 curproxy->options |= PR_O_TPXY_CIP;
3048 } else {
3049 curproxy->options |= PR_O_TPXY_ADDR;
3050 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3051 }
3052 global.last_checks |= LSTCHK_NETADM;
3053#if !defined(CONFIG_HAP_LINUX_TPROXY)
3054 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003055#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003056#else /* no TPROXY support */
3057 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003058 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003061#endif
3062 cur_arg += 2;
3063 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003064 }
3065
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003066 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3067#ifdef SO_BINDTODEVICE
3068 if (!*args[cur_arg + 1]) {
3069 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003073 }
3074 if (curproxy->iface_name)
3075 free(curproxy->iface_name);
3076
3077 curproxy->iface_name = strdup(args[cur_arg + 1]);
3078 curproxy->iface_len = strlen(curproxy->iface_name);
3079 global.last_checks |= LSTCHK_NETADM;
3080#else
3081 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3082 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003085#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003086 cur_arg += 2;
3087 continue;
3088 }
3089 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3090 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003095 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3096 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3097 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3102 regex_t *preg;
3103 if (curproxy == &defproxy) {
3104 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003108 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003110
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 if (*(args[1]) == 0 || *(args[2]) == 0) {
3112 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3113 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 }
3117
3118 preg = calloc(1, sizeof(regex_t));
3119 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3120 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 }
3124
3125 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3126 if (err) {
3127 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3128 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003131 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }
3133 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3134 regex_t *preg;
3135 if (curproxy == &defproxy) {
3136 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003140 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003142
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 if (*(args[1]) == 0) {
3144 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148
3149 preg = calloc(1, sizeof(regex_t));
3150 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3151 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
3155
3156 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003157 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3160 regex_t *preg;
3161 if (curproxy == &defproxy) {
3162 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003166 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003168
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 if (*(args[1]) == 0) {
3170 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174
3175 preg = calloc(1, sizeof(regex_t));
3176 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3177 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181
3182 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003183 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3186 regex_t *preg;
3187 if (curproxy == &defproxy) {
3188 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003192 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003194
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 if (*(args[1]) == 0) {
3196 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200
3201 preg = calloc(1, sizeof(regex_t));
3202 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3203 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
3207
3208 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003209 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3212 regex_t *preg;
3213 if (curproxy == &defproxy) {
3214 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003218 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003220
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 if (*(args[1]) == 0) {
3222 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 }
3226
3227 preg = calloc(1, sizeof(regex_t));
3228 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3229 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
3233
3234 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003235 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003237 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3238 regex_t *preg;
3239 if (curproxy == &defproxy) {
3240 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003243 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003244 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003246
Willy Tarreaub8750a82006-09-03 09:56:00 +02003247 if (*(args[1]) == 0) {
3248 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003251 }
3252
3253 preg = calloc(1, sizeof(regex_t));
3254 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3255 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003258 }
3259
3260 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003261 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003262 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003263 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3264 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003265 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003266 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003269 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003270 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003271 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003272
Willy Tarreau977b8e42006-12-29 14:19:17 +01003273 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003274 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3275 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 }
3279
3280 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003281 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003282 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003285 }
3286
3287 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003288 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003289 }
3290 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3291 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003292 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003293 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003296 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003297 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003299
Willy Tarreau977b8e42006-12-29 14:19:17 +01003300 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003301 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3302 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 }
3306
3307 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003308 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003309 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003312 }
3313
3314 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003315 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3318 regex_t *preg;
3319 if (curproxy == &defproxy) {
3320 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003324 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003326
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 if (*(args[1]) == 0 || *(args[2]) == 0) {
3328 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3329 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 }
3333
3334 preg = calloc(1, sizeof(regex_t));
3335 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3336 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 }
3340
3341 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3342 if (err) {
3343 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3344 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003348 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 }
3350 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3351 regex_t *preg;
3352 if (curproxy == &defproxy) {
3353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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 Tarreau977b8e42006-12-29 14:19:17 +01003357 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003359
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 if (*(args[1]) == 0) {
3361 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 }
3365
3366 preg = calloc(1, sizeof(regex_t));
3367 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3368 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 }
3372
3373 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003374 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 }
3376 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3377 regex_t *preg;
3378 if (curproxy == &defproxy) {
3379 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003383 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003385
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 if (*(args[1]) == 0) {
3387 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003388 err_code |= ERR_ALERT | ERR_FATAL;
3389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 }
3391
3392 preg = calloc(1, sizeof(regex_t));
3393 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3394 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 }
3398
3399 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003400 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
3402 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3403 regex_t *preg;
3404 if (curproxy == &defproxy) {
3405 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003409 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003410 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003411
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 if (*(args[1]) == 0) {
3413 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 }
3417
3418 preg = calloc(1, sizeof(regex_t));
3419 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3420 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 }
3424
3425 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003426 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
3428 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3429 regex_t *preg;
3430 if (curproxy == &defproxy) {
3431 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003435 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003437
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 if (*(args[1]) == 0) {
3439 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
3443
3444 preg = calloc(1, sizeof(regex_t));
3445 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3446 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 }
3450
3451 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003452 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003453 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003454 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3455 regex_t *preg;
3456 if (curproxy == &defproxy) {
3457 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003460 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003461 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003462 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003463
Willy Tarreaub8750a82006-09-03 09:56:00 +02003464 if (*(args[1]) == 0) {
3465 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003468 }
3469
3470 preg = calloc(1, sizeof(regex_t));
3471 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3472 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003475 }
3476
3477 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003478 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3481 if (curproxy == &defproxy) {
3482 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003485 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003486 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003487 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003488
3489 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3490 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 }
3494
3495 if (*(args[1]) == 0) {
3496 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 }
3500
3501 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003502 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
3504 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3505 regex_t *preg;
3506
3507 if (*(args[1]) == 0 || *(args[2]) == 0) {
3508 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003513 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003514 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003515
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 preg = calloc(1, sizeof(regex_t));
3517 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3518 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3522
3523 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3524 if (err) {
3525 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3526 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003530 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 }
3532 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3533 regex_t *preg;
3534 if (curproxy == &defproxy) {
3535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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 Tarreau977b8e42006-12-29 14:19:17 +01003539 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003541
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 if (*(args[1]) == 0) {
3543 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
3547
3548 preg = calloc(1, sizeof(regex_t));
3549 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3550 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }
3554
3555 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3556 if (err) {
3557 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3558 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 }
3562 }
3563 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3564 regex_t *preg;
3565 if (curproxy == &defproxy) {
3566 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003570 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003572
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 if (*(args[1]) == 0) {
3574 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 }
3578
3579 preg = calloc(1, sizeof(regex_t));
3580 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3581 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 }
3585
3586 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3587 if (err) {
3588 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3589 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 }
3593 }
3594 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3595 regex_t *preg;
3596 if (curproxy == &defproxy) {
3597 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003601 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603
3604 if (*(args[1]) == 0 || *(args[2]) == 0) {
3605 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3606 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 }
3610
3611 preg = calloc(1, sizeof(regex_t));
3612 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3613 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 }
3617
3618 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3619 if (err) {
3620 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3621 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 }
3625 }
3626 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3627 regex_t *preg;
3628 if (curproxy == &defproxy) {
3629 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003633 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003635
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 if (*(args[1]) == 0) {
3637 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 }
3641
3642 preg = calloc(1, sizeof(regex_t));
3643 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3644 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 }
3648
3649 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3650 if (err) {
3651 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3652 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 }
3656 }
3657 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3658 regex_t *preg;
3659 if (curproxy == &defproxy) {
3660 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003664 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003666
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 if (*(args[1]) == 0) {
3668 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 }
3672
3673 preg = calloc(1, sizeof(regex_t));
3674 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3675 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 }
3679
3680 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3681 if (err) {
3682 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3683 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 }
3687 }
3688 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3689 if (curproxy == &defproxy) {
3690 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003694 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696
3697 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3698 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 }
3702
3703 if (*(args[1]) == 0) {
3704 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 }
3708
3709 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3710 }
3711 else if (!strcmp(args[0], "errorloc") ||
3712 !strcmp(args[0], "errorloc302") ||
3713 !strcmp(args[0], "errorloc303")) { /* error location */
3714 int errnum, errlen;
3715 char *err;
3716
Willy Tarreau977b8e42006-12-29 14:19:17 +01003717 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003719
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003721 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 }
3725
3726 errnum = atol(args[1]);
3727 if (!strcmp(args[0], "errorloc303")) {
3728 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3729 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3730 } else {
3731 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3732 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3733 }
3734
Willy Tarreau0f772532006-12-23 20:51:41 +01003735 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3736 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003737 chunk_destroy(&curproxy->errmsg[rc]);
3738 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003739 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003742
3743 if (rc >= HTTP_ERR_SIZE) {
3744 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3745 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 free(err);
3747 }
3748 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003749 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3750 int errnum, errlen, fd;
3751 char *err;
3752 struct stat stat;
3753
3754 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003756
3757 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003758 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003761 }
3762
3763 fd = open(args[2], O_RDONLY);
3764 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3765 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3766 file, linenum, args[2], args[1]);
3767 if (fd >= 0)
3768 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003771 }
3772
Willy Tarreau27a674e2009-08-17 07:23:33 +02003773 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003774 errlen = stat.st_size;
3775 } else {
3776 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003777 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003779 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003780 }
3781
3782 err = malloc(errlen); /* malloc() must succeed during parsing */
3783 errnum = read(fd, err, errlen);
3784 if (errnum != errlen) {
3785 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3786 file, linenum, args[2], args[1]);
3787 close(fd);
3788 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003791 }
3792 close(fd);
3793
3794 errnum = atol(args[1]);
3795 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3796 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003797 chunk_destroy(&curproxy->errmsg[rc]);
3798 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003799 break;
3800 }
3801 }
3802
3803 if (rc >= HTTP_ERR_SIZE) {
3804 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3805 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003807 free(err);
3808 }
3809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003811 struct cfg_kw_list *kwl;
3812 int index;
3813
3814 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3815 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3816 if (kwl->kw[index].section != CFG_LISTEN)
3817 continue;
3818 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3819 /* prepare error message just in case */
3820 snprintf(trash, sizeof(trash),
3821 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003822 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3823 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003824 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003827 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003828 else if (rc > 0) {
3829 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_WARN;
3831 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003832 }
Willy Tarreau93893792009-07-23 13:19:11 +02003833 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003834 }
3835 }
3836 }
3837
Willy Tarreau6daf3432008-01-22 16:44:08 +01003838 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
Willy Tarreau93893792009-07-23 13:19:11 +02003842 out:
3843 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844}
3845
3846
3847/*
3848 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003849 * Returns the error code, 0 if OK, or any combination of :
3850 * - ERR_ABORT: must abort ASAP
3851 * - ERR_FATAL: we can continue parsing but not start the service
3852 * - ERR_WARN: a warning has been emitted
3853 * - ERR_ALERT: an alert has been emitted
3854 * Only the two first ones can stop processing, the two others are just
3855 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003857int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003859 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 FILE *f;
3861 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003863 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 if ((f=fopen(file,"r")) == NULL)
3866 return -1;
3867
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003868 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003869 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003870 char *end;
3871 char *args[MAX_LINE_ARGS + 1];
3872 char *line = thisline;
3873
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 linenum++;
3875
3876 end = line + strlen(line);
3877
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003878 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3879 /* Check if we reached the limit and the last char is not \n.
3880 * Watch out for the last line without the terminating '\n'!
3881 */
3882 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003883 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003885 }
3886
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003888 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 line++;
3890
3891 arg = 0;
3892 args[arg] = line;
3893
3894 while (*line && arg < MAX_LINE_ARGS) {
3895 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3896 * C equivalent value. Other combinations left unchanged (eg: \1).
3897 */
3898 if (*line == '\\') {
3899 int skip = 0;
3900 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3901 *line = line[1];
3902 skip = 1;
3903 }
3904 else if (line[1] == 'r') {
3905 *line = '\r';
3906 skip = 1;
3907 }
3908 else if (line[1] == 'n') {
3909 *line = '\n';
3910 skip = 1;
3911 }
3912 else if (line[1] == 't') {
3913 *line = '\t';
3914 skip = 1;
3915 }
3916 else if (line[1] == 'x') {
3917 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3918 unsigned char hex1, hex2;
3919 hex1 = toupper(line[2]) - '0';
3920 hex2 = toupper(line[3]) - '0';
3921 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3922 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3923 *line = (hex1<<4) + hex2;
3924 skip = 3;
3925 }
3926 else {
3927 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 }
3930 }
3931 if (skip) {
3932 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3933 end -= skip;
3934 }
3935 line++;
3936 }
3937 else if (*line == '#' || *line == '\n' || *line == '\r') {
3938 /* end of string, end of loop */
3939 *line = 0;
3940 break;
3941 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003942 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003944 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003945 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 line++;
3947 args[++arg] = line;
3948 }
3949 else {
3950 line++;
3951 }
3952 }
3953
3954 /* empty line */
3955 if (!**args)
3956 continue;
3957
Willy Tarreau540abe42007-05-02 20:50:16 +02003958 /* zero out remaining args and ensure that at least one entry
3959 * is zeroed out.
3960 */
3961 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 args[arg] = line;
3963 }
3964
Willy Tarreau3842f002009-06-14 11:39:52 +02003965 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003966 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003967 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003968 for (arg=0; *args[arg+1]; arg++)
3969 args[arg] = args[arg+1]; // shift args after inversion
3970 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003971 else if (!strcmp(args[0], "default")) {
3972 kwm = KWM_DEF;
3973 for (arg=0; *args[arg+1]; arg++)
3974 args[arg] = args[arg+1]; // shift args after inversion
3975 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003976
Willy Tarreau3842f002009-06-14 11:39:52 +02003977 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3978 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003980 }
3981
Willy Tarreau977b8e42006-12-29 14:19:17 +01003982 if (!strcmp(args[0], "listen") ||
3983 !strcmp(args[0], "frontend") ||
3984 !strcmp(args[0], "backend") ||
3985 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003986 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003988 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003989 cursection = strdup(args[0]);
3990 }
3991 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003993 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003994 cursection = strdup(args[0]);
3995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 /* else it's a section keyword */
3997
3998 switch (confsect) {
3999 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 break;
4002 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004003 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 break;
4005 default:
4006 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004009
4010 if (err_code & ERR_ABORT)
4011 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004013 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004014 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004016 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004017}
4018
Willy Tarreaubb925012009-07-23 13:36:36 +02004019/*
4020 * Returns the error code, 0 if OK, or any combination of :
4021 * - ERR_ABORT: must abort ASAP
4022 * - ERR_FATAL: we can continue parsing but not start the service
4023 * - ERR_WARN: a warning has been emitted
4024 * - ERR_ALERT: an alert has been emitted
4025 * Only the two first ones can stop processing, the two others are just
4026 * indicators.
4027 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004028int check_config_validity()
4029{
4030 int cfgerr = 0;
4031 struct proxy *curproxy = NULL;
4032 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004033 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004034 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035
4036 /*
4037 * Now, check for the integrity of all that we have collected.
4038 */
4039
4040 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004041 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004043 /* first, we will invert the proxy list order */
4044 curproxy = NULL;
4045 while (proxy) {
4046 struct proxy *next;
4047
4048 next = proxy->next;
4049 proxy->next = curproxy;
4050 curproxy = proxy;
4051 if (!next)
4052 break;
4053 proxy = next;
4054 }
4055
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004057 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 }
4061
4062 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004063 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004064 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004065 unsigned int next_id;
4066
4067 if (!curproxy->uuid) {
4068 /* proxy ID not set, use automatic numbering with first
4069 * spare entry starting with next_pxid.
4070 */
4071 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4072 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4073 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4074 next_pxid++;
4075 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004076
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004078 /* ensure we don't keep listeners uselessly bound */
4079 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004080 curproxy = curproxy->next;
4081 continue;
4082 }
4083
Willy Tarreauff01a212009-03-15 13:46:16 +01004084 switch (curproxy->mode) {
4085 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004086 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004087 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004088 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4089 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004090 cfgerr++;
4091 }
4092
4093 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004094 Warning("config : servers will be ignored for %s '%s'.\n",
4095 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004096 break;
4097
4098 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004099 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004100 break;
4101
4102 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004103 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004104 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004105 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4106 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004107 cfgerr++;
4108 }
4109 break;
4110 }
4111
4112 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004113 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4114 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 cfgerr++;
4116 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004117
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004118 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004119 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004120 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004121 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4122 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004123 cfgerr++;
4124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004126 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004127 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4128 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004129 cfgerr++;
4130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004132 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004133 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4134 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004135 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004136 }
4137 }
4138 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4139 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4140 /* If no LB algo is set in a backend, and we're not in
4141 * transparent mode, dispatch mode nor proxy mode, we
4142 * want to use balance roundrobin by default.
4143 */
4144 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4145 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 }
4147 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004148
Willy Tarreau82936582007-11-30 15:20:09 +01004149 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4150 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004151 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4152 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004153 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004154 }
4155
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004156 /* if a default backend was specified, let's find it */
4157 if (curproxy->defbe.name) {
4158 struct proxy *target;
4159
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004160 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
4161 if (!target) {
4162 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4163 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004164 cfgerr++;
4165 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004166 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4167 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004168 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004169 } else {
4170 free(curproxy->defbe.name);
4171 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004172 /* we force the backend to be present on at least all of
4173 * the frontend's processes.
4174 */
4175 target->bind_proc = curproxy->bind_proc ?
4176 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 }
4178 }
4179
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004180 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004181 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4182 /* map jump target for ACT_SETBE in req_rep chain */
4183 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004184 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004185 struct proxy *target;
4186
Willy Tarreaua496b602006-12-17 23:15:24 +01004187 if (exp->action != ACT_SETBE)
4188 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004189
4190 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
4191 if (!target) {
4192 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4193 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004194 cfgerr++;
4195 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004196 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4197 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004198 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004199 } else {
4200 free((void *)exp->replace);
4201 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004202 /* we force the backend to be present on at least all of
4203 * the frontend's processes.
4204 */
4205 target->bind_proc = curproxy->bind_proc ?
4206 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004207 }
4208 }
4209 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004210
4211 /* find the target proxy for 'use_backend' rules */
4212 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004213 struct proxy *target;
4214
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004215 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004216
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004217 if (!target) {
4218 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4219 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004220 cfgerr++;
4221 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004222 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4223 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004224 cfgerr++;
4225 } else {
4226 free((void *)rule->be.name);
4227 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004228 /* we force the backend to be present on at least all of
4229 * the frontend's processes.
4230 */
4231 target->bind_proc = curproxy->bind_proc ?
4232 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004233 }
4234 }
4235
Willy Tarreau2738a142006-07-08 17:28:09 +02004236 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004237 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004238 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004239 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004240 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004241 " | While not properly invalid, you will certainly encounter various problems\n"
4242 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004243 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004244 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004245 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004246 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004247
Willy Tarreau1fa31262007-12-03 00:36:16 +01004248 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4249 * We must still support older configurations, so let's find out whether those
4250 * parameters have been set or must be copied from contimeouts.
4251 */
4252 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004253 if (!curproxy->timeout.tarpit ||
4254 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004255 /* tarpit timeout not set. We search in the following order:
4256 * default.tarpit, curr.connect, default.connect.
4257 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004258 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004259 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004260 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004261 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004262 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004263 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004264 }
4265 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004266 (!curproxy->timeout.queue ||
4267 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004268 /* queue timeout not set. We search in the following order:
4269 * default.queue, curr.connect, default.connect.
4270 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004271 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004272 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004273 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004274 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004275 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004276 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004277 }
4278 }
4279
Willy Tarreauf3c69202006-07-09 16:42:34 +02004280 if (curproxy->options & PR_O_SSL3_CHK) {
4281 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4282 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4283 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4284 }
4285
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004286 /* The small pools required for the capture lists */
4287 if (curproxy->nb_req_cap)
4288 curproxy->req_cap_pool = create_pool("ptrcap",
4289 curproxy->nb_req_cap * sizeof(char *),
4290 MEM_F_SHARED);
4291 if (curproxy->nb_rsp_cap)
4292 curproxy->rsp_cap_pool = create_pool("ptrcap",
4293 curproxy->nb_rsp_cap * sizeof(char *),
4294 MEM_F_SHARED);
4295
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004296 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4297 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4298 MEM_F_SHARED);
4299
Willy Tarreau86034312006-12-29 00:10:33 +01004300 /* for backwards compatibility with "listen" instances, if
4301 * fullconn is not set but maxconn is set, then maxconn
4302 * is used.
4303 */
4304 if (!curproxy->fullconn)
4305 curproxy->fullconn = curproxy->maxconn;
4306
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 /* first, we will invert the servers list order */
4308 newsrv = NULL;
4309 while (curproxy->srv) {
4310 struct server *next;
4311
4312 next = curproxy->srv->next;
4313 curproxy->srv->next = newsrv;
4314 newsrv = curproxy->srv;
4315 if (!next)
4316 break;
4317 curproxy->srv = next;
4318 }
4319
Willy Tarreau20697042007-11-15 23:26:18 +01004320 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004321 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004323 /* We have to initialize the server lookup mechanism depending
4324 * on what LB algorithm was choosen.
4325 */
4326
4327 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4328 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4329 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004330 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4331 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4332 init_server_map(curproxy);
4333 } else {
4334 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4335 fwrr_init_server_groups(curproxy);
4336 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004337 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004338
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004339 case BE_LB_KIND_LC:
4340 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004341 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004342 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004343
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004344 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004345 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4346 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4347 chash_init_server_tree(curproxy);
4348 } else {
4349 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4350 init_server_map(curproxy);
4351 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004352 break;
4353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004354
4355 if (curproxy->options & PR_O_LOGASAP)
4356 curproxy->to_log &= ~LW_BYTES;
4357
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004358 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4359 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4360 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4361 proxy_type_str(curproxy), curproxy->id);
4362 err_code |= ERR_WARN;
4363 }
4364
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004366 * ensure that we're not cross-dressing a TCP server into HTTP.
4367 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004368 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004369 newsrv = curproxy->srv;
4370 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004371 if (!newsrv->puid) {
4372 /* server ID not set, use automatic numbering with first
4373 * spare entry starting with next_svid.
4374 */
4375 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4376 newsrv->conf.id.key = newsrv->puid = next_id;
4377 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4378 next_id++;
4379 }
4380
Willy Tarreau21d2af32008-02-14 20:25:24 +01004381 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004382 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4383 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004384 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004385 }
4386 newsrv = newsrv->next;
4387 }
4388
4389 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 * If this server supports a maxconn parameter, it needs a dedicated
4391 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004392 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 */
4394 newsrv = curproxy->srv;
4395 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004396 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 /* Only 'minconn' was specified, or it was higher than or equal
4398 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4399 * this will avoid further useless expensive computations.
4400 */
4401 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004402 } else if (newsrv->maxconn && !newsrv->minconn) {
4403 /* minconn was not specified, so we set it to maxconn */
4404 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004405 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004406 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4407 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004408 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004409 }
4410
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004411 if (newsrv->trackit) {
4412 struct proxy *px;
4413 struct server *srv;
4414 char *pname, *sname;
4415
4416 pname = newsrv->trackit;
4417 sname = strrchr(pname, '/');
4418
4419 if (sname)
4420 *sname++ = '\0';
4421 else {
4422 sname = pname;
4423 pname = NULL;
4424 }
4425
4426 if (pname) {
4427 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4428 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004429 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4430 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004431 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004432 cfgerr++;
4433 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004434 }
4435 } else
4436 px = curproxy;
4437
4438 srv = findserver(px, sname);
4439 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004440 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4441 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004442 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004443 cfgerr++;
4444 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004445 }
4446
4447 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004448 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004449 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004450 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004451 newsrv->id, px->id, srv->id);
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 (curproxy != px &&
4457 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004458 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004459 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004460 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004461 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004462 cfgerr++;
4463 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004464 }
4465
4466 newsrv->tracked = srv;
4467 newsrv->tracknext = srv->tracknext;
4468 srv->tracknext = newsrv;
4469
4470 free(newsrv->trackit);
4471 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004472 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 newsrv = newsrv->next;
4474 }
4475
Willy Tarreauc1a21672009-08-16 22:37:44 +02004476 if (curproxy->cap & PR_CAP_FE) {
4477 if (curproxy->tcp_req.inspect_delay ||
4478 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4479 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4480
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004481 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004482 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004483 curproxy->fe_rsp_ana |= AN_RTR_HTTP_HDR;
4484 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004485
4486 /* both TCP and HTTP must check switching rules */
4487 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4488 }
4489
4490 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004491 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004492 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004493 curproxy->be_rsp_ana |= AN_RTR_HTTP_HDR;
4494 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004495
4496 /* If the backend does requires RDP cookie persistence, we have to
4497 * enable the corresponding analyser.
4498 */
4499 if (curproxy->options2 & PR_O2_RDPC_PRST)
4500 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4501 }
4502
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004503 listener = NULL;
4504 while (curproxy->listen) {
4505 struct listener *next;
4506
4507 next = curproxy->listen->next;
4508 curproxy->listen->next = listener;
4509 listener = curproxy->listen;
4510
4511 if (!next)
4512 break;
4513
4514 curproxy->listen = next;
4515 }
4516
Willy Tarreaue6b98942007-10-29 01:09:36 +01004517 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004518 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004519 listener = curproxy->listen;
4520 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004521 if (!listener->luid) {
4522 /* listener ID not set, use automatic numbering with first
4523 * spare entry starting with next_luid.
4524 */
4525 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4526 listener->conf.id.key = listener->luid = next_id;
4527 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4528 next_id++;
4529 }
4530
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004531 /* enable separate counters */
4532 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4533 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4534 if (!listener->name) {
4535 sprintf(trash, "sock-%d", listener->luid);
4536 listener->name = strdup(trash);
4537 }
4538 }
4539
Willy Tarreaue6b98942007-10-29 01:09:36 +01004540 if (curproxy->options & PR_O_TCP_NOLING)
4541 listener->options |= LI_O_NOLINGER;
4542 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004543 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004544 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004545 listener->accept = event_accept;
4546 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004547 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004548 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004549
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004550 /* smart accept mode is automatic in HTTP mode */
4551 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4552 (curproxy->mode == PR_MODE_HTTP &&
4553 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4554 listener->options |= LI_O_NOQUICKACK;
4555
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004556 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004557 listener = listener->next;
4558 }
4559
Willy Tarreaubaaee002006-06-26 02:48:02 +02004560 curproxy = curproxy->next;
4561 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004562
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004563 /*
4564 * Recount currently required checks.
4565 */
4566
4567 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4568 int optnum;
4569
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004570 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4571 if (curproxy->options & cfg_opts[optnum].val)
4572 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004573
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004574 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4575 if (curproxy->options2 & cfg_opts2[optnum].val)
4576 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004577 }
4578
Willy Tarreaubb925012009-07-23 13:36:36 +02004579 if (cfgerr > 0)
4580 err_code |= ERR_ALERT | ERR_FATAL;
4581 out:
4582 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583}
4584
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004585/*
4586 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4587 * parsing sessions.
4588 */
4589void cfg_register_keywords(struct cfg_kw_list *kwl)
4590{
4591 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4592}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004593
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004594/*
4595 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4596 */
4597void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4598{
4599 LIST_DEL(&kwl->list);
4600 LIST_INIT(&kwl->list);
4601}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602
4603/*
4604 * Local variables:
4605 * c-indent-level: 8
4606 * c-basic-offset: 8
4607 * End:
4608 */