blob: 4e851d0f1bfcff7e3456ca6daad2c5dd39e08e8f [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 Tarreaub86db342009-11-30 11:50:16 +0100933 if (defproxy.orgto_hdr_len) {
934 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
935 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
936 }
937
Willy Tarreau977b8e42006-12-29 14:19:17 +0100938 if (curproxy->cap & PR_CAP_FE) {
939 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100940 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200941 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100942
943 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200944 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
945 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100946
947 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949
Willy Tarreau977b8e42006-12-29 14:19:17 +0100950 if (curproxy->cap & PR_CAP_BE) {
951 curproxy->fullconn = defproxy.fullconn;
952 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953
Willy Tarreau977b8e42006-12-29 14:19:17 +0100954 if (defproxy.check_req)
955 curproxy->check_req = strdup(defproxy.check_req);
956 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957
Willy Tarreau977b8e42006-12-29 14:19:17 +0100958 if (defproxy.cookie_name)
959 curproxy->cookie_name = strdup(defproxy.cookie_name);
960 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +0100961 if (defproxy.cookie_domain)
962 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +0100963
Emeric Brun647caf12009-06-30 17:57:00 +0200964 if (defproxy.rdp_cookie_name)
965 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
966 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
967
Willy Tarreau01732802007-11-01 22:48:15 +0100968 if (defproxy.url_param_name)
969 curproxy->url_param_name = strdup(defproxy.url_param_name);
970 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100971
Benoitaffb4812009-03-25 13:02:10 +0100972 if (defproxy.hh_name)
973 curproxy->hh_name = strdup(defproxy.hh_name);
974 curproxy->hh_len = defproxy.hh_len;
975 curproxy->hh_match_domain = defproxy.hh_match_domain;
976
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100977 if (defproxy.iface_name)
978 curproxy->iface_name = strdup(defproxy.iface_name);
979 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200982 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100983 if (defproxy.capture_name)
984 curproxy->capture_name = strdup(defproxy.capture_name);
985 curproxy->capture_namelen = defproxy.capture_namelen;
986 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988
Willy Tarreau977b8e42006-12-29 14:19:17 +0100989 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100990 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100991 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100992 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100993 curproxy->uri_auth = defproxy.uri_auth;
994 curproxy->mon_net = defproxy.mon_net;
995 curproxy->mon_mask = defproxy.mon_mask;
996 if (defproxy.monitor_uri)
997 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
998 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100999 if (defproxy.defbe.name)
1000 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001001 }
1002
1003 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001004 curproxy->timeout.connect = defproxy.timeout.connect;
1005 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001006 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001007 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001008 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001009 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001010 curproxy->source_addr = defproxy.source_addr;
1011 }
1012
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013 curproxy->mode = defproxy.mode;
1014 curproxy->logfac1 = defproxy.logfac1;
1015 curproxy->logsrv1 = defproxy.logsrv1;
1016 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001017 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001018 curproxy->logfac2 = defproxy.logfac2;
1019 curproxy->logsrv2 = defproxy.logsrv2;
1020 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001021 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001023 curproxy->conf.used_listener_id = EB_ROOT;
1024 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001025
Willy Tarreau93893792009-07-23 13:19:11 +02001026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027 }
1028 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1029 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001030 /* FIXME-20070101: we should do this too at the end of the
1031 * config parsing to free all default values.
1032 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001033 free(defproxy.check_req);
1034 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001035 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001036 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001037 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001038 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001039 free(defproxy.capture_name);
1040 free(defproxy.monitor_uri);
1041 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001042 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001043 free(defproxy.fwdfor_hdr_name);
1044 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001045 free(defproxy.orgto_hdr_name);
1046 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001047
Willy Tarreaua534fea2008-08-03 12:19:50 +02001048 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001049 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001050
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 /* we cannot free uri_auth because it might already be used */
1052 init_default_instance();
1053 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001054 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
1057 else if (curproxy == NULL) {
1058 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 }
1062
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063
1064 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001066 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001067 int cur_arg;
1068
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 if (curproxy == &defproxy) {
1070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001074 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001075 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076
1077 if (strchr(args[1], ':') == NULL) {
1078 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001083
1084 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001085 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001089
Willy Tarreau90a570f2009-10-04 20:54:54 +02001090 new_listen = curproxy->listen;
1091 while (new_listen != last_listen) {
1092 new_listen->conf.file = file;
1093 new_listen->conf.line = linenum;
1094 new_listen = new_listen->next;
1095 }
1096
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001097 cur_arg = 2;
1098 while (*(args[cur_arg])) {
1099 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1100#ifdef SO_BINDTODEVICE
1101 struct listener *l;
1102
1103 if (!*args[cur_arg + 1]) {
1104 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001108 }
1109
1110 for (l = curproxy->listen; l != last_listen; l = l->next)
1111 l->interface = strdup(args[cur_arg + 1]);
1112
1113 global.last_checks |= LSTCHK_NETADM;
1114
1115 cur_arg += 2;
1116 continue;
1117#else
1118 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1119 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001122#endif
1123 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001124 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1125#ifdef TCP_MAXSEG
1126 struct listener *l;
1127 int mss;
1128
1129 if (!*args[cur_arg + 1]) {
1130 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001134 }
1135
1136 mss = str2uic(args[cur_arg + 1]);
1137 if (mss < 1 || mss > 65535) {
1138 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1139 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001142 }
1143
1144 for (l = curproxy->listen; l != last_listen; l = l->next)
1145 l->maxseg = mss;
1146
1147 cur_arg += 2;
1148 continue;
1149#else
1150 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1151 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001154#endif
1155 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001156
1157 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1158#ifdef TCP_DEFER_ACCEPT
1159 struct listener *l;
1160
1161 for (l = curproxy->listen; l != last_listen; l = l->next)
1162 l->options |= LI_O_DEF_ACCEPT;
1163
1164 cur_arg ++;
1165 continue;
1166#else
1167 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1168 file, linenum, args[0], args[cur_arg]);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto out;
1171#endif
1172 }
1173
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001174 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001175#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001176 struct listener *l;
1177
1178 for (l = curproxy->listen; l != last_listen; l = l->next)
1179 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001180
1181 cur_arg ++;
1182 continue;
1183#else
1184 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1185 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001188#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001189 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001190
1191 if (!strcmp(args[cur_arg], "name")) {
1192 struct listener *l;
1193
1194 for (l = curproxy->listen; l != last_listen; l = l->next)
1195 l->name = strdup(args[cur_arg + 1]);
1196
1197 cur_arg += 2;
1198 continue;
1199 }
1200
1201 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001202 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001203 struct listener *l;
1204
1205 if (curproxy->listen->next != last_listen) {
1206 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1207 file, linenum, args[cur_arg]);
1208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
1210 }
1211
1212 if (!*args[cur_arg + 1]) {
1213 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1214 file, linenum, args[cur_arg]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218
1219 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001220 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001221
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001222 if (curproxy->listen->luid <= 0) {
1223 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001224 file, linenum);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001229 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1230 if (node) {
1231 l = container_of(node, struct listener, conf.id);
1232 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1233 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1238
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001239 cur_arg += 2;
1240 continue;
1241 }
1242
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001243 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 }
1251 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1252 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1253 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1254 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001258 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001260
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 /* flush useless bits */
1262 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001265 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001267 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001268
Willy Tarreau1c47f852006-07-09 08:22:27 +02001269 if (!*args[1]) {
1270 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001274 }
1275
Willy Tarreaua534fea2008-08-03 12:19:50 +02001276 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001277 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001278 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001279 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001280 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1281
Willy Tarreau93893792009-07-23 13:19:11 +02001282 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1285 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1286 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1287 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1288 else {
1289 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 }
1293 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001294 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001295 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001296
1297 if (curproxy == &defproxy) {
1298 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001302 }
1303
1304 if (!*args[1]) {
1305 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001307 err_code |= ERR_ALERT | ERR_FATAL;
1308 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001309 }
1310
1311 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001312 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001313
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001314 if (curproxy->uuid <= 0) {
1315 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001316 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001319 }
1320
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001321 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1322 if (node) {
1323 struct proxy *target = container_of(node, struct proxy, conf.id);
1324 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1325 file, linenum, proxy_type_str(curproxy), curproxy->id,
1326 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
1329 }
1330 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001331 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001332 else if (!strcmp(args[0], "description")) {
1333 int i, len=0;
1334 char *d;
1335
1336 if (!*args[1]) {
1337 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1338 file, linenum, args[0]);
1339 return -1;
1340 }
1341
1342 for(i=1; *args[i]; i++)
1343 len += strlen(args[i])+1;
1344
1345 d = (char *)calloc(1, len);
1346 curproxy->desc = d;
1347
1348 d += sprintf(d, "%s", args[1]);
1349 for(i=2; *args[i]; i++)
1350 d += sprintf(d, " %s", args[i]);
1351
1352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1354 curproxy->state = PR_STSTOPPED;
1355 }
1356 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1357 curproxy->state = PR_STNEW;
1358 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001359 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1360 int cur_arg = 1;
1361 unsigned int set = 0;
1362
1363 while (*args[cur_arg]) {
1364 int u;
1365 if (strcmp(args[cur_arg], "all") == 0) {
1366 set = 0;
1367 break;
1368 }
1369 else if (strcmp(args[cur_arg], "odd") == 0) {
1370 set |= 0x55555555;
1371 }
1372 else if (strcmp(args[cur_arg], "even") == 0) {
1373 set |= 0xAAAAAAAA;
1374 }
1375 else {
1376 u = str2uic(args[cur_arg]);
1377 if (u < 1 || u > 32) {
1378 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1379 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001382 }
1383 if (u > global.nbproc) {
1384 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1385 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001386 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001387 }
1388 set |= 1 << (u - 1);
1389 }
1390 cur_arg++;
1391 }
1392 curproxy->bind_proc = set;
1393 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001394 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001395 if (curproxy == &defproxy) {
1396 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001399 }
1400
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001401 err = invalid_char(args[1]);
1402 if (err) {
1403 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1404 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001406 }
1407
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001408 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1409 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1410 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001413 }
1414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1416 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417
Willy Tarreau977b8e42006-12-29 14:19:17 +01001418 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001419 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 if (*(args[1]) == 0) {
1422 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1423 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001424 err_code |= ERR_ALERT | ERR_FATAL;
1425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001427
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001428 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001429 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 curproxy->cookie_name = strdup(args[1]);
1431 curproxy->cookie_len = strlen(curproxy->cookie_name);
1432
1433 cur_arg = 2;
1434 while (*(args[cur_arg])) {
1435 if (!strcmp(args[cur_arg], "rewrite")) {
1436 curproxy->options |= PR_O_COOK_RW;
1437 }
1438 else if (!strcmp(args[cur_arg], "indirect")) {
1439 curproxy->options |= PR_O_COOK_IND;
1440 }
1441 else if (!strcmp(args[cur_arg], "insert")) {
1442 curproxy->options |= PR_O_COOK_INS;
1443 }
1444 else if (!strcmp(args[cur_arg], "nocache")) {
1445 curproxy->options |= PR_O_COOK_NOC;
1446 }
1447 else if (!strcmp(args[cur_arg], "postonly")) {
1448 curproxy->options |= PR_O_COOK_POST;
1449 }
1450 else if (!strcmp(args[cur_arg], "prefix")) {
1451 curproxy->options |= PR_O_COOK_PFX;
1452 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001453 else if (!strcmp(args[cur_arg], "domain")) {
1454 if (!*args[cur_arg + 1]) {
1455 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1456 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001459 }
1460
Willy Tarreau3d8fbb62009-12-03 23:10:56 +01001461 if (*args[cur_arg + 1] != '.' && !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001462 /* rfc2109, 4.3.2 Rejecting Cookies */
1463 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
Willy Tarreau3d8fbb62009-12-03 23:10:56 +01001464 " dots and does not start with a dot.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001465 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001468 }
1469
1470 err = invalid_domainchar(args[cur_arg + 1]);
1471 if (err) {
1472 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1473 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001476 }
1477
Willy Tarreau68a897b2009-12-03 23:28:34 +01001478 if (!curproxy->cookie_domain) {
1479 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1480 } else {
1481 /* one domain was already specified, add another one by
1482 * building the string which will be returned along with
1483 * the cookie.
1484 */
1485 char *new_ptr;
1486 int new_len = strlen(curproxy->cookie_domain) +
1487 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1488 new_ptr = malloc(new_len);
1489 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1490 free(curproxy->cookie_domain);
1491 curproxy->cookie_domain = new_ptr;
1492 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001493 cur_arg++;
1494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001496 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 }
1501 cur_arg++;
1502 }
1503 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1504 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 }
1508
1509 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1510 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1511 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001512 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513 }
1514 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001515 else if (!strcmp(args[0], "persist")) { /* persist */
1516 if (*(args[1]) == 0) {
1517 Alert("parsing [%s:%d] : missing persist method.\n",
1518 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001521 }
1522
1523 if (!strncmp(args[1], "rdp-cookie", 10)) {
1524 curproxy->options2 |= PR_O2_RDPC_PRST;
1525
1526 if (*(args[1] + 10 ) == '(') { /* cookie name */
1527 const char *beg, *end;
1528
1529 beg = args[1] + 11;
1530 end = strchr(beg, ')');
1531
1532 if (!end || end == beg) {
1533 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001535 err_code |= ERR_ALERT | ERR_FATAL;
1536 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001537 }
1538
1539 free(curproxy->rdp_cookie_name);
1540 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1541 curproxy->rdp_cookie_len = end-beg;
1542 }
1543 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1544 free(curproxy->rdp_cookie_name);
1545 curproxy->rdp_cookie_name = strdup("msts");
1546 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1547 }
1548 else { /* syntax */
1549 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1550 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001553 }
1554 }
1555 else {
1556 Alert("parsing [%s:%d] : unknown persist method.\n",
1557 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001558 err_code |= ERR_ALERT | ERR_FATAL;
1559 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001560 }
1561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001563 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564
Willy Tarreau977b8e42006-12-29 14:19:17 +01001565 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001566 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001569 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 }
1574 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001575 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 curproxy->appsession_name = strdup(args[1]);
1577 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1578 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001579 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1580 if (err) {
1581 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1582 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001583 err_code |= ERR_ALERT | ERR_FATAL;
1584 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001585 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001586 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001587
Willy Tarreau51041c72007-09-09 21:56:53 +02001588 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001590 err_code |= ERR_ALERT | ERR_ABORT;
1591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001593
1594 cur_arg = 6;
1595 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001596 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1597 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001598 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001599 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001600 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001601 } else if (!strcmp(args[cur_arg], "prefix")) {
1602 curproxy->options2 |= PR_O2_AS_PFX;
1603 } else if (!strcmp(args[cur_arg], "mode")) {
1604 if (!*args[cur_arg + 1]) {
1605 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1606 file, linenum, args[0], args[cur_arg]);
1607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
1609 }
1610
1611 cur_arg++;
1612 if (!strcmp(args[cur_arg], "query-string")) {
1613 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1614 curproxy->options2 |= PR_O2_AS_M_QS;
1615 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1616 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1617 curproxy->options2 |= PR_O2_AS_M_PP;
1618 } else {
1619 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001624 cur_arg++;
1625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 } /* Url App Session */
1627 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001628 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001630
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 if (*(args[4]) == 0) {
1633 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001638 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 curproxy->capture_name = strdup(args[2]);
1640 curproxy->capture_namelen = strlen(curproxy->capture_name);
1641 curproxy->capture_len = atol(args[4]);
1642 if (curproxy->capture_len >= CAPTURE_LEN) {
1643 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1644 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 curproxy->capture_len = CAPTURE_LEN - 1;
1647 }
1648 curproxy->to_log |= LW_COOKIE;
1649 }
1650 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1651 struct cap_hdr *hdr;
1652
1653 if (curproxy == &defproxy) {
1654 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001655 err_code |= ERR_ALERT | ERR_FATAL;
1656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 }
1658
1659 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1660 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1661 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
1665
1666 hdr = calloc(sizeof(struct cap_hdr), 1);
1667 hdr->next = curproxy->req_cap;
1668 hdr->name = strdup(args[3]);
1669 hdr->namelen = strlen(args[3]);
1670 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001671 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 hdr->index = curproxy->nb_req_cap++;
1673 curproxy->req_cap = hdr;
1674 curproxy->to_log |= LW_REQHDR;
1675 }
1676 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1677 struct cap_hdr *hdr;
1678
1679 if (curproxy == &defproxy) {
1680 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_ALERT | ERR_FATAL;
1682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 }
1684
1685 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1686 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1687 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
1691 hdr = calloc(sizeof(struct cap_hdr), 1);
1692 hdr->next = curproxy->rsp_cap;
1693 hdr->name = strdup(args[3]);
1694 hdr->namelen = strlen(args[3]);
1695 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001696 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 hdr->index = curproxy->nb_rsp_cap++;
1698 curproxy->rsp_cap = hdr;
1699 curproxy->to_log |= LW_RSPHDR;
1700 }
1701 else {
1702 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1703 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 }
1707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 if (*(args[1]) == 0) {
1713 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 }
1718 curproxy->conn_retries = atol(args[1]);
1719 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001720 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1721 int pol = ACL_COND_NONE;
1722 struct acl_cond *cond;
1723
Willy Tarreaub099aca2008-10-12 17:26:37 +02001724 if (curproxy == &defproxy) {
1725 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001728 }
1729
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001730 if (!strcmp(args[1], "if"))
1731 pol = ACL_COND_IF;
1732 else if (!strcmp(args[1], "unless"))
1733 pol = ACL_COND_UNLESS;
1734
1735 if (pol == ACL_COND_NONE) {
1736 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001740 }
1741
1742 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1743 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1744 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001747 }
Willy Tarreau88922352009-10-04 22:02:50 +02001748 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001749 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001750 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001751 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001752 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001753 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001754 else if (!strcmp(args[0], "redirect")) {
1755 int pol = ACL_COND_NONE;
1756 struct acl_cond *cond;
1757 struct redirect_rule *rule;
1758 int cur_arg;
1759 int type = REDIRECT_TYPE_NONE;
1760 int code = 302;
1761 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001762 char *cookie = NULL;
1763 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001764 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001765
1766 cur_arg = 1;
1767 while (*(args[cur_arg])) {
1768 if (!strcmp(args[cur_arg], "location")) {
1769 if (!*args[cur_arg + 1]) {
1770 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1771 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001774 }
1775
1776 type = REDIRECT_TYPE_LOCATION;
1777 cur_arg++;
1778 destination = args[cur_arg];
1779 }
1780 else if (!strcmp(args[cur_arg], "prefix")) {
1781 if (!*args[cur_arg + 1]) {
1782 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1783 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001786 }
1787
1788 type = REDIRECT_TYPE_PREFIX;
1789 cur_arg++;
1790 destination = args[cur_arg];
1791 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001792 else if (!strcmp(args[cur_arg], "set-cookie")) {
1793 if (!*args[cur_arg + 1]) {
1794 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1795 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001798 }
1799
1800 cur_arg++;
1801 cookie = args[cur_arg];
1802 cookie_set = 1;
1803 }
1804 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1805 if (!*args[cur_arg + 1]) {
1806 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1807 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001810 }
1811
1812 cur_arg++;
1813 cookie = args[cur_arg];
1814 cookie_set = 0;
1815 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001816 else if (!strcmp(args[cur_arg],"code")) {
1817 if (!*args[cur_arg + 1]) {
1818 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1819 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001822 }
1823 cur_arg++;
1824 code = atol(args[cur_arg]);
1825 if (code < 301 || code > 303) {
1826 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1827 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001828 err_code |= ERR_ALERT | ERR_FATAL;
1829 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001830 }
1831 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001832 else if (!strcmp(args[cur_arg],"drop-query")) {
1833 flags |= REDIRECT_FLAG_DROP_QS;
1834 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001835 else if (!strcmp(args[cur_arg], "if")) {
1836 pol = ACL_COND_IF;
1837 cur_arg++;
1838 break;
1839 }
1840 else if (!strcmp(args[cur_arg], "unless")) {
1841 pol = ACL_COND_UNLESS;
1842 cur_arg++;
1843 break;
1844 }
1845 else {
1846 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1847 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001850 }
1851 cur_arg++;
1852 }
1853
1854 if (type == REDIRECT_TYPE_NONE) {
1855 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1856 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001859 }
1860
1861 if (pol == ACL_COND_NONE) {
1862 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1863 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001864 err_code |= ERR_ALERT | ERR_FATAL;
1865 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001866 }
1867
1868 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001869 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001870 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001873 }
1874
Willy Tarreau88922352009-10-04 22:02:50 +02001875 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001876 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001877 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001878 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1879 rule->cond = cond;
1880 rule->rdr_str = strdup(destination);
1881 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001882 if (cookie) {
1883 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1884 * a clear consists in appending "; Max-Age=0" at the end.
1885 */
1886 rule->cookie_len = strlen(cookie);
1887 if (cookie_set)
1888 rule->cookie_str = strdup(cookie);
1889 else {
1890 rule->cookie_str = malloc(rule->cookie_len + 12);
1891 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1892 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1893 rule->cookie_len += 11;
1894 }
1895 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001896 rule->type = type;
1897 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001898 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001899 LIST_INIT(&rule->list);
1900 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001901 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001902 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001903 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001904 int pol = ACL_COND_NONE;
1905 struct acl_cond *cond;
1906 struct switching_rule *rule;
1907
Willy Tarreaub099aca2008-10-12 17:26:37 +02001908 if (curproxy == &defproxy) {
1909 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001910 err_code |= ERR_ALERT | ERR_FATAL;
1911 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001912 }
1913
Willy Tarreau55ea7572007-06-17 19:56:27 +02001914 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001916
1917 if (*(args[1]) == 0) {
1918 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001921 }
1922
1923 if (!strcmp(args[2], "if"))
1924 pol = ACL_COND_IF;
1925 else if (!strcmp(args[2], "unless"))
1926 pol = ACL_COND_UNLESS;
1927
1928 if (pol == ACL_COND_NONE) {
1929 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001933 }
1934
1935 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001936 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001937 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001940 }
1941
Willy Tarreau88922352009-10-04 22:02:50 +02001942 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001943 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001944 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001945 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001946 struct acl *acl;
1947 const char *name;
1948
1949 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1950 name = acl ? acl->name : "(unknown)";
1951 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1952 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001954 }
1955
Willy Tarreau55ea7572007-06-17 19:56:27 +02001956 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1957 rule->cond = cond;
1958 rule->be.name = strdup(args[1]);
1959 LIST_INIT(&rule->list);
1960 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001963 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001964 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001965
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1967 curproxy->uri_auth = NULL; /* we must detach from the default config */
1968
1969 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001970 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 +02001971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 } else if (!strcmp(args[1], "uri")) {
1974 if (*(args[2]) == 0) {
1975 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1979 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_ABORT;
1981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 }
1983 } else if (!strcmp(args[1], "realm")) {
1984 if (*(args[2]) == 0) {
1985 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1989 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001990 err_code |= ERR_ALERT | ERR_ABORT;
1991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001993 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001994 unsigned interval;
1995
1996 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1997 if (err) {
1998 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1999 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002002 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2003 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002004 err_code |= ERR_ALERT | ERR_ABORT;
2005 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 } else if (!strcmp(args[1], "auth")) {
2008 if (*(args[2]) == 0) {
2009 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2013 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002014 err_code |= ERR_ALERT | ERR_ABORT;
2015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002016 }
2017 } else if (!strcmp(args[1], "scope")) {
2018 if (*(args[2]) == 0) {
2019 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2023 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_ALERT | ERR_ABORT;
2025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 }
2027 } else if (!strcmp(args[1], "enable")) {
2028 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2029 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002030 err_code |= ERR_ALERT | ERR_ABORT;
2031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002033 } else if (!strcmp(args[1], "hide-version")) {
2034 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2035 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_ABORT;
2037 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002038 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002039 } else if (!strcmp(args[1], "show-node")) {
2040
2041 if (*args[2]) {
2042 int i;
2043 char c;
2044
2045 for (i=0; args[2][i]; i++) {
2046 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002047 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002048 break;
2049 }
2050
2051 if (!i || args[2][i]) {
2052 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2053 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2054 file, linenum, args[0], args[1]);
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058 }
2059
2060 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2061 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2062 err_code |= ERR_ALERT | ERR_ABORT;
2063 goto out;
2064 }
2065 } else if (!strcmp(args[1], "show-desc")) {
2066 char *desc = NULL;
2067
2068 if (*args[2]) {
2069 int i, len=0;
2070 char *d;
2071
2072 for(i=2; *args[i]; i++)
2073 len += strlen(args[i])+1;
2074
2075 desc = d = (char *)calloc(1, len);
2076
2077 d += sprintf(d, "%s", args[2]);
2078 for(i=3; *args[i]; i++)
2079 d += sprintf(d, " %s", args[i]);
2080 }
2081
2082 if (!*args[2] && !global.desc)
2083 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2084 file, linenum, args[1]);
2085 else {
2086 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2087 free(desc);
2088 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2089 err_code |= ERR_ALERT | ERR_ABORT;
2090 goto out;
2091 }
2092 free(desc);
2093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002095 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 }
2100 }
2101 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002102 int optnum;
2103
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002104 if (*(args[1]) == '\0') {
2105 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_ALERT | ERR_FATAL;
2108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002110
2111 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2112 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002113 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2114 err_code |= ERR_WARN;
2115 goto out;
2116 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002117
Willy Tarreau3842f002009-06-14 11:39:52 +02002118 curproxy->no_options &= ~cfg_opts[optnum].val;
2119 curproxy->options &= ~cfg_opts[optnum].val;
2120
2121 switch (kwm) {
2122 case KWM_STD:
2123 curproxy->options |= cfg_opts[optnum].val;
2124 break;
2125 case KWM_NO:
2126 curproxy->no_options |= cfg_opts[optnum].val;
2127 break;
2128 case KWM_DEF: /* already cleared */
2129 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002130 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002131
Willy Tarreau93893792009-07-23 13:19:11 +02002132 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002133 }
2134 }
2135
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002136 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2137 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002138 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2139 err_code |= ERR_WARN;
2140 goto out;
2141 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002142
Willy Tarreau3842f002009-06-14 11:39:52 +02002143 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2144 curproxy->options2 &= ~cfg_opts2[optnum].val;
2145
2146 switch (kwm) {
2147 case KWM_STD:
2148 curproxy->options2 |= cfg_opts2[optnum].val;
2149 break;
2150 case KWM_NO:
2151 curproxy->no_options2 |= cfg_opts2[optnum].val;
2152 break;
2153 case KWM_DEF: /* already cleared */
2154 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002155 }
Willy Tarreau93893792009-07-23 13:19:11 +02002156 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002157 }
2158 }
2159
Willy Tarreau3842f002009-06-14 11:39:52 +02002160 if (kwm != KWM_STD) {
2161 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002162 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002163 err_code |= ERR_ALERT | ERR_FATAL;
2164 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002165 }
2166
Emeric Brun3a058f32009-06-30 18:26:00 +02002167 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002169 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002171 if (*(args[2]) != '\0') {
2172 if (!strcmp(args[2], "clf")) {
2173 curproxy->options2 |= PR_O2_CLFLOG;
2174 } else {
2175 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002178 }
2179 }
2180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 else if (!strcmp(args[1], "tcplog"))
2182 /* generate a detailed TCP log */
2183 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 else if (!strcmp(args[1], "tcpka")) {
2185 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002186 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002188
2189 if (curproxy->cap & PR_CAP_FE)
2190 curproxy->options |= PR_O_TCP_CLI_KA;
2191 if (curproxy->cap & PR_CAP_BE)
2192 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 }
2194 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002195 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002196 err_code |= ERR_WARN;
2197
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002199 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002200 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002201 curproxy->options &= ~PR_O_SMTP_CHK;
2202 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 if (!*args[2]) { /* no argument */
2204 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2205 curproxy->check_len = strlen(DEF_CHECK_REQ);
2206 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002207 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 curproxy->check_req = (char *)malloc(reqlen);
2209 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2210 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2211 } else { /* more arguments : METHOD URI [HTTP_VER] */
2212 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2213 if (*args[4])
2214 reqlen += strlen(args[4]);
2215 else
2216 reqlen += strlen("HTTP/1.0");
2217
2218 curproxy->check_req = (char *)malloc(reqlen);
2219 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2220 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2221 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002222 }
2223 else if (!strcmp(args[1], "ssl-hello-chk")) {
2224 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002225 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002227
Willy Tarreaua534fea2008-08-03 12:19:50 +02002228 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002229 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002230 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002231 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
Willy Tarreau23677902007-05-08 23:50:35 +02002233 else if (!strcmp(args[1], "smtpchk")) {
2234 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002235 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002236 curproxy->options &= ~PR_O_HTTP_CHK;
2237 curproxy->options &= ~PR_O_SSL3_CHK;
2238 curproxy->options |= PR_O_SMTP_CHK;
2239
2240 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2241 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2242 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2243 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2244 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2245 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2246 curproxy->check_req = (char *)malloc(reqlen);
2247 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2248 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2249 } else {
2250 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2251 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2252 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2253 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2254 }
2255 }
2256 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002257 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002258 int cur_arg;
2259
2260 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2261 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002262 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002263
2264 curproxy->options |= PR_O_FWDFOR;
2265
2266 free(curproxy->fwdfor_hdr_name);
2267 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2268 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2269
2270 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2271 cur_arg = 2;
2272 while (*(args[cur_arg])) {
2273 if (!strcmp(args[cur_arg], "except")) {
2274 /* suboption except - needs additional argument for it */
2275 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2276 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002280 }
2281 /* flush useless bits */
2282 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002283 cur_arg += 2;
2284 } else if (!strcmp(args[cur_arg], "header")) {
2285 /* suboption header - needs additional argument for it */
2286 if (*(args[cur_arg+1]) == 0) {
2287 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2288 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002291 }
2292 free(curproxy->fwdfor_hdr_name);
2293 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2294 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2295 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002296 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002297 /* unknown suboption - catchall */
2298 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2299 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002302 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002303 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002304 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002305 else if (!strcmp(args[1], "originalto")) {
2306 int cur_arg;
2307
2308 /* insert x-original-to field, but not for the IP address listed as an except.
2309 * set default options (ie: bitfield, header name, etc)
2310 */
2311
2312 curproxy->options |= PR_O_ORGTO;
2313
2314 free(curproxy->orgto_hdr_name);
2315 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2316 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2317
2318 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2319 cur_arg = 2;
2320 while (*(args[cur_arg])) {
2321 if (!strcmp(args[cur_arg], "except")) {
2322 /* suboption except - needs additional argument for it */
2323 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2324 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2325 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002328 }
2329 /* flush useless bits */
2330 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2331 cur_arg += 2;
2332 } else if (!strcmp(args[cur_arg], "header")) {
2333 /* suboption header - needs additional argument for it */
2334 if (*(args[cur_arg+1]) == 0) {
2335 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2336 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002339 }
2340 free(curproxy->orgto_hdr_name);
2341 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2342 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2343 cur_arg += 2;
2344 } else {
2345 /* unknown suboption - catchall */
2346 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2347 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002350 }
2351 } /* end while loop */
2352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 else {
2354 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 }
Willy Tarreau93893792009-07-23 13:19:11 +02002358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002360 else if (!strcmp(args[0], "default_backend")) {
2361 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002363
2364 if (*(args[1]) == 0) {
2365 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002368 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002369 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002370 curproxy->defbe.name = strdup(args[1]);
2371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002373 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002375
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002376 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2377 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 /* enable reconnections to dispatch */
2380 curproxy->options |= PR_O_REDISP;
2381 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002382 else if (!strcmp(args[0], "http-check")) {
2383 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002385
2386 if (strcmp(args[1], "disable-on-404") == 0) {
2387 /* enable a graceful server shutdown on an HTTP 404 response */
2388 curproxy->options |= PR_O_DISABLE404;
2389 }
2390 else {
2391 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002394 }
2395 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002396 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002397 if (curproxy == &defproxy) {
2398 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002401 }
2402
Willy Tarreaub80c2302007-11-30 20:51:32 +01002403 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002405
2406 if (strcmp(args[1], "fail") == 0) {
2407 /* add a condition to fail monitor requests */
2408 int pol = ACL_COND_NONE;
2409 struct acl_cond *cond;
2410
2411 if (!strcmp(args[2], "if"))
2412 pol = ACL_COND_IF;
2413 else if (!strcmp(args[2], "unless"))
2414 pol = ACL_COND_UNLESS;
2415
2416 if (pol == ACL_COND_NONE) {
2417 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2418 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002421 }
2422
2423 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2424 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2425 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002428 }
Willy Tarreau88922352009-10-04 22:02:50 +02002429 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002430 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002431 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002432 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2433 }
2434 else {
2435 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002438 }
2439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440#ifdef TPROXY
2441 else if (!strcmp(args[0], "transparent")) {
2442 /* enable transparent proxy connections */
2443 curproxy->options |= PR_O_TRANSP;
2444 }
2445#endif
2446 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002449
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 if (*(args[1]) == 0) {
2451 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
2455 curproxy->maxconn = atol(args[1]);
2456 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002457 else if (!strcmp(args[0], "backlog")) { /* backlog */
2458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002460
2461 if (*(args[1]) == 0) {
2462 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002465 }
2466 curproxy->backlog = atol(args[1]);
2467 }
Willy Tarreau86034312006-12-29 00:10:33 +01002468 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471
Willy Tarreau86034312006-12-29 00:10:33 +01002472 if (*(args[1]) == 0) {
2473 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002476 }
2477 curproxy->fullconn = atol(args[1]);
2478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2480 if (*(args[1]) == 0) {
2481 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002485 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2486 if (err) {
2487 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2488 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002491 }
2492 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 }
2494 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2495 if (curproxy == &defproxy) {
2496 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002500 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002501 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002502
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 if (strchr(args[1], ':') == NULL) {
2504 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 }
2508 curproxy->dispatch_addr = *str2sa(args[1]);
2509 }
2510 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002511 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002512 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002513
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002514 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002515 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2516 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002520 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002521 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2523 err_code |= ERR_WARN;
2524
2525 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2526 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2527 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2528 }
2529 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2530 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2531 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2532 }
2533 else {
2534 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
2537 }
2538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 else if (!strcmp(args[0], "server")) { /* server address */
2540 int cur_arg;
2541 char *rport;
2542 char *raddr;
2543 short realport;
2544 int do_check;
2545
2546 if (curproxy == &defproxy) {
2547 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002551 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553
2554 if (!*args[2]) {
2555 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002560
2561 err = invalid_char(args[1]);
2562 if (err) {
2563 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2564 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002567 }
2568
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2570 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_ABORT;
2572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
2574
2575 /* the servers are linked backwards first */
2576 newsrv->next = curproxy->srv;
2577 curproxy->srv = newsrv;
2578 newsrv->proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002579 newsrv->conf.file = file;
2580 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581
2582 LIST_INIT(&newsrv->pendconns);
2583 do_check = 0;
2584 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002585 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 newsrv->id = strdup(args[1]);
2587
2588 /* several ways to check the port component :
2589 * - IP => port=+0, relative
2590 * - IP: => port=+0, relative
2591 * - IP:N => port=N, absolute
2592 * - IP:+N => port=+N, relative
2593 * - IP:-N => port=-N, relative
2594 */
2595 raddr = strdup(args[2]);
2596 rport = strchr(raddr, ':');
2597 if (rport) {
2598 *rport++ = 0;
2599 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002600 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 newsrv->state |= SRV_MAPPORTS;
2602 } else {
2603 realport = 0;
2604 newsrv->state |= SRV_MAPPORTS;
2605 }
2606
2607 newsrv->addr = *str2sa(raddr);
2608 newsrv->addr.sin_port = htons(realport);
2609 free(raddr);
2610
2611 newsrv->curfd = -1; /* no health-check in progress */
2612 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002613 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2614 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 newsrv->rise = DEF_RISETIME;
2616 newsrv->fall = DEF_FALLTIME;
2617 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau975c50b2009-10-10 19:34:06 +02002618 newsrv->uweight = newsrv->iweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002619 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002620 newsrv->slowstart = 0;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002621 newsrv->onerror = DEF_HANA_ONERR;
2622 newsrv->consecutive_errors_limit = DEF_HANA_ERRLIMIT;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002623
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 cur_arg = 3;
2625 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002626 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002627 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002628
2629 if (!*args[cur_arg + 1]) {
2630 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2631 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002634 }
2635
2636 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002637 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002638
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002639 if (newsrv->puid <= 0) {
2640 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002641 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002644 }
2645
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002646 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2647 if (node) {
2648 struct server *target = container_of(node, struct server, conf.id);
2649 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
2650 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
2653 }
2654 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002655 cur_arg += 2;
2656 }
2657 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 newsrv->cookie = strdup(args[cur_arg + 1]);
2659 newsrv->cklen = strlen(args[cur_arg + 1]);
2660 cur_arg += 2;
2661 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002662 else if (!strcmp(args[cur_arg], "redir")) {
2663 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2664 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2665 cur_arg += 2;
2666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002668 if (!*args[cur_arg + 1]) {
2669 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2670 file, linenum, args[cur_arg]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002676 if (newsrv->rise <= 0) {
2677 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2678 file, linenum, args[cur_arg]);
2679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
2681 }
2682
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 newsrv->health = newsrv->rise;
2684 cur_arg += 2;
2685 }
2686 else if (!strcmp(args[cur_arg], "fall")) {
2687 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002688
2689 if (!*args[cur_arg + 1]) {
2690 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2691 file, linenum, args[cur_arg]);
2692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
2695
2696 if (newsrv->fall <= 0) {
2697 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2698 file, linenum, args[cur_arg]);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
2701 }
2702
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 cur_arg += 2;
2704 }
2705 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002706 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2707 if (err) {
2708 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2709 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002712 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002713 if (val <= 0) {
2714 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2715 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002718 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002719 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 cur_arg += 2;
2721 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002722 else if (!strcmp(args[cur_arg], "fastinter")) {
2723 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2724 if (err) {
2725 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2726 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002729 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002730 if (val <= 0) {
2731 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2732 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002735 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002736 newsrv->fastinter = val;
2737 cur_arg += 2;
2738 }
2739 else if (!strcmp(args[cur_arg], "downinter")) {
2740 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2741 if (err) {
2742 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2743 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002746 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002747 if (val <= 0) {
2748 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2749 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002752 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002753 newsrv->downinter = val;
2754 cur_arg += 2;
2755 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002756 else if (!strcmp(args[cur_arg], "addr")) {
2757 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002758 cur_arg += 2;
2759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 else if (!strcmp(args[cur_arg], "port")) {
2761 newsrv->check_port = atol(args[cur_arg + 1]);
2762 cur_arg += 2;
2763 }
2764 else if (!strcmp(args[cur_arg], "backup")) {
2765 newsrv->state |= SRV_BACKUP;
2766 cur_arg ++;
2767 }
2768 else if (!strcmp(args[cur_arg], "weight")) {
2769 int w;
2770 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002771 if (w < 0 || w > 256) {
2772 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02002777 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 cur_arg += 2;
2779 }
2780 else if (!strcmp(args[cur_arg], "minconn")) {
2781 newsrv->minconn = atol(args[cur_arg + 1]);
2782 cur_arg += 2;
2783 }
2784 else if (!strcmp(args[cur_arg], "maxconn")) {
2785 newsrv->maxconn = atol(args[cur_arg + 1]);
2786 cur_arg += 2;
2787 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002788 else if (!strcmp(args[cur_arg], "maxqueue")) {
2789 newsrv->maxqueue = atol(args[cur_arg + 1]);
2790 cur_arg += 2;
2791 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002792 else if (!strcmp(args[cur_arg], "slowstart")) {
2793 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002794 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002795 if (err) {
2796 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2797 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002800 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002801 if (val <= 0) {
2802 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2803 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002806 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002807 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002808 cur_arg += 2;
2809 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002810 else if (!strcmp(args[cur_arg], "track")) {
2811
2812 if (!*args[cur_arg + 1]) {
2813 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2814 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002817 }
2818
2819 newsrv->trackit = strdup(args[cur_arg + 1]);
2820
2821 cur_arg += 2;
2822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 else if (!strcmp(args[cur_arg], "check")) {
2824 global.maxsock++;
2825 do_check = 1;
2826 cur_arg += 1;
2827 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01002828 else if (!strcmp(args[cur_arg], "observe")) {
2829 if (!strcmp(args[cur_arg + 1], "none"))
2830 newsrv->observe = HANA_OBS_NONE;
2831 else if (!strcmp(args[cur_arg + 1], "layer4"))
2832 newsrv->observe = HANA_OBS_LAYER4;
2833 else if (!strcmp(args[cur_arg + 1], "layer7")) {
2834 if (curproxy->mode != PR_MODE_HTTP) {
2835 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
2836 file, linenum, args[cur_arg + 1]);
2837 err_code |= ERR_ALERT;
2838 }
2839 newsrv->observe = HANA_OBS_LAYER7;
2840 }
2841 else {
2842 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
2843 "'l4events', 'http-responses' but get '%s'\n",
2844 file, linenum, args[cur_arg], args[cur_arg + 1]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848
2849 cur_arg += 2;
2850 }
2851 else if (!strcmp(args[cur_arg], "on-error")) {
2852 if (!strcmp(args[cur_arg + 1], "fastinter"))
2853 newsrv->onerror = HANA_ONERR_FASTINTER;
2854 else if (!strcmp(args[cur_arg + 1], "fail-check"))
2855 newsrv->onerror = HANA_ONERR_FAILCHK;
2856 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
2857 newsrv->onerror = HANA_ONERR_SUDDTH;
2858 else if (!strcmp(args[cur_arg + 1], "mark-down"))
2859 newsrv->onerror = HANA_ONERR_MARKDWN;
2860 else {
2861 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
2862 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
2863 file, linenum, args[cur_arg], args[cur_arg + 1]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867
2868 cur_arg += 2;
2869 }
2870 else if (!strcmp(args[cur_arg], "error-limit")) {
2871 if (!*args[cur_arg + 1]) {
2872 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2873 file, linenum, args[cur_arg]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877
2878 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
2879
2880 if (newsrv->consecutive_errors_limit <= 0) {
2881 Alert("parsing [%s:%d]: %s has to be > 0.\n",
2882 file, linenum, args[cur_arg]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002888 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002890#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002891 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002892 file, linenum, "source", "usesrc");
2893#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002894 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002896#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 }
2900 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002901 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2902
2903 if (port_low != port_high) {
2904 int i;
2905 if (port_low <= 0 || port_low > 65535 ||
2906 port_high <= 0 || port_high > 65535 ||
2907 port_low > port_high) {
2908 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2909 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002912 }
2913 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2914 for (i = 0; i < newsrv->sport_range->size; i++)
2915 newsrv->sport_range->ports[i] = port_low + i;
2916 }
2917
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002919 while (*(args[cur_arg])) {
2920 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002921#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2922#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002923 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2924 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2925 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002928 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002929#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002930 if (!*args[cur_arg + 1]) {
2931 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2932 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002935 }
2936 if (!strcmp(args[cur_arg + 1], "client")) {
2937 newsrv->state |= SRV_TPROXY_CLI;
2938 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2939 newsrv->state |= SRV_TPROXY_CIP;
2940 } else {
2941 newsrv->state |= SRV_TPROXY_ADDR;
2942 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2943 }
2944 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002945#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002946 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002947#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002948 cur_arg += 2;
2949 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002950#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002951 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002952 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002955#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2956 } /* "usesrc" */
2957
2958 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2959#ifdef SO_BINDTODEVICE
2960 if (!*args[cur_arg + 1]) {
2961 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002965 }
2966 if (newsrv->iface_name)
2967 free(newsrv->iface_name);
2968
2969 newsrv->iface_name = strdup(args[cur_arg + 1]);
2970 newsrv->iface_len = strlen(newsrv->iface_name);
2971 global.last_checks |= LSTCHK_NETADM;
2972#else
2973 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2974 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002977#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002978 cur_arg += 2;
2979 continue;
2980 }
2981 /* this keyword in not an option of "source" */
2982 break;
2983 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002985 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2986 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2987 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002992 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 +02002993 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 }
2997 }
2998
2999 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003000 if (newsrv->trackit) {
3001 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3002 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003005 }
3006
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003007 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3008 newsrv->check_port = newsrv->check_addr.sin_port;
3009
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3011 newsrv->check_port = realport; /* by default */
3012 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003013 /* not yet valid, because no port was set on
3014 * the server either. We'll check if we have
3015 * a known port on the first listener.
3016 */
3017 struct listener *l;
3018 l = curproxy->listen;
3019 if (l) {
3020 int port;
3021 port = (l->addr.ss_family == AF_INET6)
3022 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3023 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3024 newsrv->check_port = port;
3025 }
3026 }
3027 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3029 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003033
3034 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035 newsrv->state |= SRV_CHECKED;
3036 }
3037
3038 if (newsrv->state & SRV_BACKUP)
3039 curproxy->srv_bck++;
3040 else
3041 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003042
3043 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 }
3045 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003046 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 int facility;
3048
3049 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3050 curproxy->logfac1 = global.logfac1;
3051 curproxy->logsrv1 = global.logsrv1;
3052 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003053 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 curproxy->logfac2 = global.logfac2;
3055 curproxy->logsrv2 = global.logsrv2;
3056 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003057 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 }
3059 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003060 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061
3062 facility = get_log_facility(args[2]);
3063 if (facility < 0) {
3064 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3065 exit(1);
3066 }
3067
3068 level = 7; /* max syslog level = debug */
3069 if (*(args[3])) {
3070 level = get_log_level(args[3]);
3071 if (level < 0) {
3072 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3073 exit(1);
3074 }
3075 }
3076
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003077 minlvl = 0; /* limit syslog level to this level (emerg) */
3078 if (*(args[4])) {
3079 minlvl = get_log_level(args[4]);
3080 if (level < 0) {
3081 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3082 exit(1);
3083 }
3084 }
3085
Robert Tsai81ae1952007-12-05 10:47:29 +01003086 if (args[1][0] == '/') {
3087 logsrv.u.addr.sa_family = AF_UNIX;
3088 logsrv.u.un = *str2sun(args[1]);
3089 } else {
3090 logsrv.u.addr.sa_family = AF_INET;
3091 logsrv.u.in = *str2sa(args[1]);
3092 if (!logsrv.u.in.sin_port) {
3093 logsrv.u.in.sin_port =
3094 htons(SYSLOG_PORT);
3095 }
3096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097
3098 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003099 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 curproxy->logfac1 = facility;
3101 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003102 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
3104 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003105 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 curproxy->logfac2 = facility;
3107 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003108 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
3110 else {
3111 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 }
3115 }
3116 else {
3117 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3118 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 }
3122 }
3123 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003124 int cur_arg;
3125
Willy Tarreau977b8e42006-12-29 14:19:17 +01003126 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003128
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003130 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3131 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003135
3136 /* we must first clear any optional default setting */
3137 curproxy->options &= ~PR_O_TPXY_MASK;
3138 free(curproxy->iface_name);
3139 curproxy->iface_name = NULL;
3140 curproxy->iface_len = 0;
3141
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 curproxy->source_addr = *str2sa(args[1]);
3143 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003144
3145 cur_arg = 2;
3146 while (*(args[cur_arg])) {
3147 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003148#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3149#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003150 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3151 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3152 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003155 }
3156#endif
3157 if (!*args[cur_arg + 1]) {
3158 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3159 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003162 }
3163
3164 if (!strcmp(args[cur_arg + 1], "client")) {
3165 curproxy->options |= PR_O_TPXY_CLI;
3166 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3167 curproxy->options |= PR_O_TPXY_CIP;
3168 } else {
3169 curproxy->options |= PR_O_TPXY_ADDR;
3170 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3171 }
3172 global.last_checks |= LSTCHK_NETADM;
3173#if !defined(CONFIG_HAP_LINUX_TPROXY)
3174 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003175#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003176#else /* no TPROXY support */
3177 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003178 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003181#endif
3182 cur_arg += 2;
3183 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003184 }
3185
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003186 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3187#ifdef SO_BINDTODEVICE
3188 if (!*args[cur_arg + 1]) {
3189 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3190 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003193 }
3194 if (curproxy->iface_name)
3195 free(curproxy->iface_name);
3196
3197 curproxy->iface_name = strdup(args[cur_arg + 1]);
3198 curproxy->iface_len = strlen(curproxy->iface_name);
3199 global.last_checks |= LSTCHK_NETADM;
3200#else
3201 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3202 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003205#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003206 cur_arg += 2;
3207 continue;
3208 }
3209 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3210 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003215 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3216 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3217 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3222 regex_t *preg;
3223 if (curproxy == &defproxy) {
3224 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003229 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003230
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 if (*(args[1]) == 0 || *(args[2]) == 0) {
3232 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3233 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 }
3237
3238 preg = calloc(1, sizeof(regex_t));
3239 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3240 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
3244
3245 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3246 if (err) {
3247 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3248 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003249 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003251 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 }
3253 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3254 regex_t *preg;
3255 if (curproxy == &defproxy) {
3256 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003260 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003262
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 if (*(args[1]) == 0) {
3264 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 }
3268
3269 preg = calloc(1, sizeof(regex_t));
3270 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3271 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 }
3275
3276 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003277 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 }
3279 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3280 regex_t *preg;
3281 if (curproxy == &defproxy) {
3282 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003286 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003288
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 if (*(args[1]) == 0) {
3290 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003291 err_code |= ERR_ALERT | ERR_FATAL;
3292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 }
3294
3295 preg = calloc(1, sizeof(regex_t));
3296 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3297 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301
3302 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003303 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
3305 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3306 regex_t *preg;
3307 if (curproxy == &defproxy) {
3308 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003312 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003314
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 if (*(args[1]) == 0) {
3316 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 }
3320
3321 preg = calloc(1, sizeof(regex_t));
3322 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3323 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
3327
3328 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003329 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3332 regex_t *preg;
3333 if (curproxy == &defproxy) {
3334 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003338 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003340
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 if (*(args[1]) == 0) {
3342 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 }
3346
3347 preg = calloc(1, sizeof(regex_t));
3348 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3349 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
3353
3354 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003355 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003357 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3358 regex_t *preg;
3359 if (curproxy == &defproxy) {
3360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003363 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003364 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003366
Willy Tarreaub8750a82006-09-03 09:56:00 +02003367 if (*(args[1]) == 0) {
3368 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003371 }
3372
3373 preg = calloc(1, sizeof(regex_t));
3374 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3375 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003378 }
3379
3380 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003381 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003382 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003383 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3384 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003385 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003386 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003389 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003390 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003392
Willy Tarreau977b8e42006-12-29 14:19:17 +01003393 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003394 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003398 }
3399
3400 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003401 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003402 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003405 }
3406
3407 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003408 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003409 }
3410 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3411 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003412 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003413 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003416 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003417 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003418 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003419
Willy Tarreau977b8e42006-12-29 14:19:17 +01003420 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003421 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3422 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003425 }
3426
3427 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003428 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003429 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003432 }
3433
3434 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003435 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3438 regex_t *preg;
3439 if (curproxy == &defproxy) {
3440 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003443 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003444 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003445 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003446
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 if (*(args[1]) == 0 || *(args[2]) == 0) {
3448 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3449 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 }
3453
3454 preg = calloc(1, sizeof(regex_t));
3455 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3456 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003457 err_code |= ERR_ALERT | ERR_FATAL;
3458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003459 }
3460
3461 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3462 if (err) {
3463 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3464 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003468 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469 }
3470 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3471 regex_t *preg;
3472 if (curproxy == &defproxy) {
3473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003477 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003479
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 if (*(args[1]) == 0) {
3481 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 }
3485
3486 preg = calloc(1, sizeof(regex_t));
3487 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3488 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 }
3492
3493 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003494 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 }
3496 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3497 regex_t *preg;
3498 if (curproxy == &defproxy) {
3499 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003503 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003505
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 if (*(args[1]) == 0) {
3507 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
3511
3512 preg = calloc(1, sizeof(regex_t));
3513 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3514 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 }
3518
3519 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003520 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 }
3522 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3523 regex_t *preg;
3524 if (curproxy == &defproxy) {
3525 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003529 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003531
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 if (*(args[1]) == 0) {
3533 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
3537
3538 preg = calloc(1, sizeof(regex_t));
3539 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3540 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
3544
3545 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003546 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 }
3548 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3549 regex_t *preg;
3550 if (curproxy == &defproxy) {
3551 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003555 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003557
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 if (*(args[1]) == 0) {
3559 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 }
3563
3564 preg = calloc(1, sizeof(regex_t));
3565 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3566 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3570
3571 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003572 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003574 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3575 regex_t *preg;
3576 if (curproxy == &defproxy) {
3577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003580 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003581 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003583
Willy Tarreaub8750a82006-09-03 09:56:00 +02003584 if (*(args[1]) == 0) {
3585 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003588 }
3589
3590 preg = calloc(1, sizeof(regex_t));
3591 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3592 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003595 }
3596
3597 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003598 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3601 if (curproxy == &defproxy) {
3602 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003606 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608
3609 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3610 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 }
3614
3615 if (*(args[1]) == 0) {
3616 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 }
3620
3621 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003622 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 }
3624 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3625 regex_t *preg;
3626
3627 if (*(args[1]) == 0 || *(args[2]) == 0) {
3628 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3629 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 preg = calloc(1, sizeof(regex_t));
3637 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3638 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 }
3642
3643 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3644 if (err) {
3645 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3646 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003650 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
3652 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3653 regex_t *preg;
3654 if (curproxy == &defproxy) {
3655 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003659 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003661
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 if (*(args[1]) == 0) {
3663 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 }
3667
3668 preg = calloc(1, sizeof(regex_t));
3669 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3670 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 }
3674
3675 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3676 if (err) {
3677 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3678 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003681 }
3682 }
3683 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3684 regex_t *preg;
3685 if (curproxy == &defproxy) {
3686 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003690 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003691 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003692
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 if (*(args[1]) == 0) {
3694 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 }
3698
3699 preg = calloc(1, sizeof(regex_t));
3700 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3701 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
3705
3706 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3707 if (err) {
3708 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3709 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 }
3713 }
3714 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3715 regex_t *preg;
3716 if (curproxy == &defproxy) {
3717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003721 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723
3724 if (*(args[1]) == 0 || *(args[2]) == 0) {
3725 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 }
3730
3731 preg = calloc(1, sizeof(regex_t));
3732 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3733 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
3737
3738 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3739 if (err) {
3740 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3741 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_ALERT | ERR_FATAL;
3743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 }
3745 }
3746 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3747 regex_t *preg;
3748 if (curproxy == &defproxy) {
3749 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003753 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003755
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 if (*(args[1]) == 0) {
3757 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 }
3761
3762 preg = calloc(1, sizeof(regex_t));
3763 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3764 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
3768
3769 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3770 if (err) {
3771 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3772 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 }
3776 }
3777 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3778 regex_t *preg;
3779 if (curproxy == &defproxy) {
3780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003784 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003786
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 if (*(args[1]) == 0) {
3788 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 }
3792
3793 preg = calloc(1, sizeof(regex_t));
3794 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3795 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 }
3799
3800 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3801 if (err) {
3802 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3803 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 }
3807 }
3808 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3809 if (curproxy == &defproxy) {
3810 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003814 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816
3817 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3818 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 }
3822
3823 if (*(args[1]) == 0) {
3824 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 }
3828
3829 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3830 }
3831 else if (!strcmp(args[0], "errorloc") ||
3832 !strcmp(args[0], "errorloc302") ||
3833 !strcmp(args[0], "errorloc303")) { /* error location */
3834 int errnum, errlen;
3835 char *err;
3836
Willy Tarreau977b8e42006-12-29 14:19:17 +01003837 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003839
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003841 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
3845
3846 errnum = atol(args[1]);
3847 if (!strcmp(args[0], "errorloc303")) {
3848 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3849 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3850 } else {
3851 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3852 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3853 }
3854
Willy Tarreau0f772532006-12-23 20:51:41 +01003855 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3856 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003857 chunk_destroy(&curproxy->errmsg[rc]);
3858 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003859 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003862
3863 if (rc >= HTTP_ERR_SIZE) {
3864 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3865 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 free(err);
3867 }
3868 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003869 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3870 int errnum, errlen, fd;
3871 char *err;
3872 struct stat stat;
3873
3874 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003876
3877 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003878 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003881 }
3882
3883 fd = open(args[2], O_RDONLY);
3884 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3885 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3886 file, linenum, args[2], args[1]);
3887 if (fd >= 0)
3888 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003891 }
3892
Willy Tarreau27a674e2009-08-17 07:23:33 +02003893 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003894 errlen = stat.st_size;
3895 } else {
3896 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003897 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003899 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003900 }
3901
3902 err = malloc(errlen); /* malloc() must succeed during parsing */
3903 errnum = read(fd, err, errlen);
3904 if (errnum != errlen) {
3905 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3906 file, linenum, args[2], args[1]);
3907 close(fd);
3908 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003911 }
3912 close(fd);
3913
3914 errnum = atol(args[1]);
3915 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3916 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003917 chunk_destroy(&curproxy->errmsg[rc]);
3918 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003919 break;
3920 }
3921 }
3922
3923 if (rc >= HTTP_ERR_SIZE) {
3924 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3925 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003927 free(err);
3928 }
3929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003931 struct cfg_kw_list *kwl;
3932 int index;
3933
3934 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3935 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3936 if (kwl->kw[index].section != CFG_LISTEN)
3937 continue;
3938 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3939 /* prepare error message just in case */
3940 snprintf(trash, sizeof(trash),
3941 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003942 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3943 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003944 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003947 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003948 else if (rc > 0) {
3949 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_WARN;
3951 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003952 }
Willy Tarreau93893792009-07-23 13:19:11 +02003953 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003954 }
3955 }
3956 }
3957
Willy Tarreau6daf3432008-01-22 16:44:08 +01003958 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
Willy Tarreau93893792009-07-23 13:19:11 +02003962 out:
3963 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964}
3965
3966
3967/*
3968 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003969 * Returns the error code, 0 if OK, or any combination of :
3970 * - ERR_ABORT: must abort ASAP
3971 * - ERR_FATAL: we can continue parsing but not start the service
3972 * - ERR_WARN: a warning has been emitted
3973 * - ERR_ALERT: an alert has been emitted
3974 * Only the two first ones can stop processing, the two others are just
3975 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003977int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003979 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980 FILE *f;
3981 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003983 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 if ((f=fopen(file,"r")) == NULL)
3986 return -1;
3987
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003988 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003989 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003990 char *end;
3991 char *args[MAX_LINE_ARGS + 1];
3992 char *line = thisline;
3993
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 linenum++;
3995
3996 end = line + strlen(line);
3997
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003998 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3999 /* Check if we reached the limit and the last char is not \n.
4000 * Watch out for the last line without the terminating '\n'!
4001 */
4002 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004003 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004005 }
4006
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004008 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 line++;
4010
4011 arg = 0;
4012 args[arg] = line;
4013
4014 while (*line && arg < MAX_LINE_ARGS) {
4015 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4016 * C equivalent value. Other combinations left unchanged (eg: \1).
4017 */
4018 if (*line == '\\') {
4019 int skip = 0;
4020 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4021 *line = line[1];
4022 skip = 1;
4023 }
4024 else if (line[1] == 'r') {
4025 *line = '\r';
4026 skip = 1;
4027 }
4028 else if (line[1] == 'n') {
4029 *line = '\n';
4030 skip = 1;
4031 }
4032 else if (line[1] == 't') {
4033 *line = '\t';
4034 skip = 1;
4035 }
4036 else if (line[1] == 'x') {
4037 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
4038 unsigned char hex1, hex2;
4039 hex1 = toupper(line[2]) - '0';
4040 hex2 = toupper(line[3]) - '0';
4041 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4042 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4043 *line = (hex1<<4) + hex2;
4044 skip = 3;
4045 }
4046 else {
4047 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004048 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 }
4050 }
4051 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004052 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 end -= skip;
4054 }
4055 line++;
4056 }
4057 else if (*line == '#' || *line == '\n' || *line == '\r') {
4058 /* end of string, end of loop */
4059 *line = 0;
4060 break;
4061 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004062 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004064 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004065 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 line++;
4067 args[++arg] = line;
4068 }
4069 else {
4070 line++;
4071 }
4072 }
4073
4074 /* empty line */
4075 if (!**args)
4076 continue;
4077
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004078 if (*line) {
4079 /* we had to stop due to too many args.
4080 * Let's terminate the string, print the offending part then cut the
4081 * last arg.
4082 */
4083 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4084 line++;
4085 *line = '\0';
4086
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004087 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004088 file, linenum, arg + 1, args[arg] - thisline + 1, args[arg]);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 args[arg] = line;
4091 }
4092
Willy Tarreau540abe42007-05-02 20:50:16 +02004093 /* zero out remaining args and ensure that at least one entry
4094 * is zeroed out.
4095 */
4096 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004097 args[arg] = line;
4098 }
4099
Willy Tarreau3842f002009-06-14 11:39:52 +02004100 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004101 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004102 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004103 for (arg=0; *args[arg+1]; arg++)
4104 args[arg] = args[arg+1]; // shift args after inversion
4105 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004106 else if (!strcmp(args[0], "default")) {
4107 kwm = KWM_DEF;
4108 for (arg=0; *args[arg+1]; arg++)
4109 args[arg] = args[arg+1]; // shift args after inversion
4110 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004111
Willy Tarreau3842f002009-06-14 11:39:52 +02004112 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4113 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004115 }
4116
Willy Tarreau977b8e42006-12-29 14:19:17 +01004117 if (!strcmp(args[0], "listen") ||
4118 !strcmp(args[0], "frontend") ||
4119 !strcmp(args[0], "backend") ||
4120 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004121 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004123 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004124 cursection = strdup(args[0]);
4125 }
4126 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004128 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004129 cursection = strdup(args[0]);
4130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 /* else it's a section keyword */
4132
4133 switch (confsect) {
4134 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 break;
4137 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004138 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 break;
4140 default:
4141 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004144
4145 if (err_code & ERR_ABORT)
4146 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004148 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004149 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004151 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004152}
4153
Willy Tarreaubb925012009-07-23 13:36:36 +02004154/*
4155 * Returns the error code, 0 if OK, or any combination of :
4156 * - ERR_ABORT: must abort ASAP
4157 * - ERR_FATAL: we can continue parsing but not start the service
4158 * - ERR_WARN: a warning has been emitted
4159 * - ERR_ALERT: an alert has been emitted
4160 * Only the two first ones can stop processing, the two others are just
4161 * indicators.
4162 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004163int check_config_validity()
4164{
4165 int cfgerr = 0;
4166 struct proxy *curproxy = NULL;
4167 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004168 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004169 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170
4171 /*
4172 * Now, check for the integrity of all that we have collected.
4173 */
4174
4175 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004176 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004178 /* first, we will invert the proxy list order */
4179 curproxy = NULL;
4180 while (proxy) {
4181 struct proxy *next;
4182
4183 next = proxy->next;
4184 proxy->next = curproxy;
4185 curproxy = proxy;
4186 if (!next)
4187 break;
4188 proxy = next;
4189 }
4190
Willy Tarreaubaaee002006-06-26 02:48:02 +02004191 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004192 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 }
4196
4197 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004198 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004199 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004200 unsigned int next_id;
4201
4202 if (!curproxy->uuid) {
4203 /* proxy ID not set, use automatic numbering with first
4204 * spare entry starting with next_pxid.
4205 */
4206 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4207 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4208 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4209 next_pxid++;
4210 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004211
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004213 /* ensure we don't keep listeners uselessly bound */
4214 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 curproxy = curproxy->next;
4216 continue;
4217 }
4218
Willy Tarreauff01a212009-03-15 13:46:16 +01004219 switch (curproxy->mode) {
4220 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004221 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004222 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004223 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4224 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004225 cfgerr++;
4226 }
4227
4228 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004229 Warning("config : servers will be ignored for %s '%s'.\n",
4230 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004231 break;
4232
4233 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004234 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004235 break;
4236
4237 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004238 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004239 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004240 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4241 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004242 cfgerr++;
4243 }
4244 break;
4245 }
4246
4247 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004248 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4249 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 cfgerr++;
4251 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004252
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004253 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004254 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004255 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004256 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4257 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004258 cfgerr++;
4259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004261 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004262 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4263 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004264 cfgerr++;
4265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004266#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004267 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004268 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4269 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004270 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004271 }
4272 }
4273 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4274 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4275 /* If no LB algo is set in a backend, and we're not in
4276 * transparent mode, dispatch mode nor proxy mode, we
4277 * want to use balance roundrobin by default.
4278 */
4279 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4280 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 }
4282 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004283
Willy Tarreau82936582007-11-30 15:20:09 +01004284 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4285 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004286 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4287 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004288 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004289 }
4290
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004291 /* if a default backend was specified, let's find it */
4292 if (curproxy->defbe.name) {
4293 struct proxy *target;
4294
Alex Williams96532db2009-11-01 21:27:13 -05004295 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004296 if (!target) {
4297 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4298 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004299 cfgerr++;
4300 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004301 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4302 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004303 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004304 } else {
4305 free(curproxy->defbe.name);
4306 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004307 /* we force the backend to be present on at least all of
4308 * the frontend's processes.
4309 */
4310 target->bind_proc = curproxy->bind_proc ?
4311 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 }
4313 }
4314
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004315 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004316 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4317 /* map jump target for ACT_SETBE in req_rep chain */
4318 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004319 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004320 struct proxy *target;
4321
Willy Tarreaua496b602006-12-17 23:15:24 +01004322 if (exp->action != ACT_SETBE)
4323 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004324
Alex Williams96532db2009-11-01 21:27:13 -05004325 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004326 if (!target) {
4327 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4328 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004329 cfgerr++;
4330 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004331 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4332 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004333 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004334 } else {
4335 free((void *)exp->replace);
4336 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004337 /* we force the backend to be present on at least all of
4338 * the frontend's processes.
4339 */
4340 target->bind_proc = curproxy->bind_proc ?
4341 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004342 }
4343 }
4344 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004345
4346 /* find the target proxy for 'use_backend' rules */
4347 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004348 struct proxy *target;
4349
Alex Williams96532db2009-11-01 21:27:13 -05004350 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004351
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004352 if (!target) {
4353 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4354 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004355 cfgerr++;
4356 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004357 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4358 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004359 cfgerr++;
4360 } else {
4361 free((void *)rule->be.name);
4362 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004363 /* we force the backend to be present on at least all of
4364 * the frontend's processes.
4365 */
4366 target->bind_proc = curproxy->bind_proc ?
4367 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004368 }
4369 }
4370
Willy Tarreau2738a142006-07-08 17:28:09 +02004371 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004372 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004373 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004374 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004375 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004376 " | While not properly invalid, you will certainly encounter various problems\n"
4377 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004378 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004379 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004380 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004381 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004382
Willy Tarreau1fa31262007-12-03 00:36:16 +01004383 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4384 * We must still support older configurations, so let's find out whether those
4385 * parameters have been set or must be copied from contimeouts.
4386 */
4387 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004388 if (!curproxy->timeout.tarpit ||
4389 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004390 /* tarpit timeout not set. We search in the following order:
4391 * default.tarpit, curr.connect, default.connect.
4392 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004393 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004394 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004395 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004396 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004397 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004398 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004399 }
4400 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004401 (!curproxy->timeout.queue ||
4402 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004403 /* queue timeout not set. We search in the following order:
4404 * default.queue, curr.connect, default.connect.
4405 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004406 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004407 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004408 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004409 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004410 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004411 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004412 }
4413 }
4414
Willy Tarreauf3c69202006-07-09 16:42:34 +02004415 if (curproxy->options & PR_O_SSL3_CHK) {
4416 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4417 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4418 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4419 }
4420
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004421 /* The small pools required for the capture lists */
4422 if (curproxy->nb_req_cap)
4423 curproxy->req_cap_pool = create_pool("ptrcap",
4424 curproxy->nb_req_cap * sizeof(char *),
4425 MEM_F_SHARED);
4426 if (curproxy->nb_rsp_cap)
4427 curproxy->rsp_cap_pool = create_pool("ptrcap",
4428 curproxy->nb_rsp_cap * sizeof(char *),
4429 MEM_F_SHARED);
4430
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004431 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4432 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4433 MEM_F_SHARED);
4434
Willy Tarreau86034312006-12-29 00:10:33 +01004435 /* for backwards compatibility with "listen" instances, if
4436 * fullconn is not set but maxconn is set, then maxconn
4437 * is used.
4438 */
4439 if (!curproxy->fullconn)
4440 curproxy->fullconn = curproxy->maxconn;
4441
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 /* first, we will invert the servers list order */
4443 newsrv = NULL;
4444 while (curproxy->srv) {
4445 struct server *next;
4446
4447 next = curproxy->srv->next;
4448 curproxy->srv->next = newsrv;
4449 newsrv = curproxy->srv;
4450 if (!next)
4451 break;
4452 curproxy->srv = next;
4453 }
4454
Willy Tarreau20697042007-11-15 23:26:18 +01004455 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004456 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004458 /* We have to initialize the server lookup mechanism depending
4459 * on what LB algorithm was choosen.
4460 */
4461
4462 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4463 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4464 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004465 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4466 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4467 init_server_map(curproxy);
4468 } else {
4469 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4470 fwrr_init_server_groups(curproxy);
4471 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004472 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004473
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004474 case BE_LB_KIND_LC:
4475 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004476 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004477 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004478
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004479 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004480 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4481 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4482 chash_init_server_tree(curproxy);
4483 } else {
4484 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4485 init_server_map(curproxy);
4486 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004487 break;
4488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489
4490 if (curproxy->options & PR_O_LOGASAP)
4491 curproxy->to_log &= ~LW_BYTES;
4492
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004493 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4494 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4495 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4496 proxy_type_str(curproxy), curproxy->id);
4497 err_code |= ERR_WARN;
4498 }
4499
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004501 * ensure that we're not cross-dressing a TCP server into HTTP.
4502 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004503 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004504 newsrv = curproxy->srv;
4505 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004506 if (!newsrv->puid) {
4507 /* server ID not set, use automatic numbering with first
4508 * spare entry starting with next_svid.
4509 */
4510 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4511 newsrv->conf.id.key = newsrv->puid = next_id;
4512 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4513 next_id++;
4514 }
4515
Willy Tarreau21d2af32008-02-14 20:25:24 +01004516 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004517 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4518 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004519 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004520 }
4521 newsrv = newsrv->next;
4522 }
4523
4524 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 * If this server supports a maxconn parameter, it needs a dedicated
4526 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004527 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004528 */
4529 newsrv = curproxy->srv;
4530 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004531 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 /* Only 'minconn' was specified, or it was higher than or equal
4533 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4534 * this will avoid further useless expensive computations.
4535 */
4536 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004537 } else if (newsrv->maxconn && !newsrv->minconn) {
4538 /* minconn was not specified, so we set it to maxconn */
4539 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004540 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004541 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4542 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004543 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 }
4545
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004546 if (newsrv->trackit) {
4547 struct proxy *px;
4548 struct server *srv;
4549 char *pname, *sname;
4550
4551 pname = newsrv->trackit;
4552 sname = strrchr(pname, '/');
4553
4554 if (sname)
4555 *sname++ = '\0';
4556 else {
4557 sname = pname;
4558 pname = NULL;
4559 }
4560
4561 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004562 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004563 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004564 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4565 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004566 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004567 cfgerr++;
4568 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004569 }
4570 } else
4571 px = curproxy;
4572
4573 srv = findserver(px, sname);
4574 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004575 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4576 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004577 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004578 cfgerr++;
4579 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004580 }
4581
4582 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004583 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004584 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004585 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004586 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004587 cfgerr++;
4588 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004589 }
4590
4591 if (curproxy != px &&
4592 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004593 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004594 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004595 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004596 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004597 cfgerr++;
4598 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004599 }
4600
4601 newsrv->tracked = srv;
4602 newsrv->tracknext = srv->tracknext;
4603 srv->tracknext = newsrv;
4604
4605 free(newsrv->trackit);
4606 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004607 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 newsrv = newsrv->next;
4609 }
4610
Willy Tarreauc1a21672009-08-16 22:37:44 +02004611 if (curproxy->cap & PR_CAP_FE) {
4612 if (curproxy->tcp_req.inspect_delay ||
4613 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4614 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4615
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004616 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004617 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004618 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004619 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004620
4621 /* both TCP and HTTP must check switching rules */
4622 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4623 }
4624
4625 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004626 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004627 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004628 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004629 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004630
4631 /* If the backend does requires RDP cookie persistence, we have to
4632 * enable the corresponding analyser.
4633 */
4634 if (curproxy->options2 & PR_O2_RDPC_PRST)
4635 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4636 }
4637
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004638 listener = NULL;
4639 while (curproxy->listen) {
4640 struct listener *next;
4641
4642 next = curproxy->listen->next;
4643 curproxy->listen->next = listener;
4644 listener = curproxy->listen;
4645
4646 if (!next)
4647 break;
4648
4649 curproxy->listen = next;
4650 }
4651
Willy Tarreaue6b98942007-10-29 01:09:36 +01004652 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004653 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004654 listener = curproxy->listen;
4655 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004656 if (!listener->luid) {
4657 /* listener ID not set, use automatic numbering with first
4658 * spare entry starting with next_luid.
4659 */
4660 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4661 listener->conf.id.key = listener->luid = next_id;
4662 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4663 next_id++;
4664 }
4665
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004666 /* enable separate counters */
4667 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4668 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4669 if (!listener->name) {
4670 sprintf(trash, "sock-%d", listener->luid);
4671 listener->name = strdup(trash);
4672 }
4673 }
4674
Willy Tarreaue6b98942007-10-29 01:09:36 +01004675 if (curproxy->options & PR_O_TCP_NOLING)
4676 listener->options |= LI_O_NOLINGER;
4677 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004678 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004679 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004680 listener->accept = event_accept;
4681 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004682 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004683 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004684
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004685 /* smart accept mode is automatic in HTTP mode */
4686 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4687 (curproxy->mode == PR_MODE_HTTP &&
4688 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4689 listener->options |= LI_O_NOQUICKACK;
4690
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004691 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004692 listener = listener->next;
4693 }
4694
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 curproxy = curproxy->next;
4696 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004697
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004698 /*
4699 * Recount currently required checks.
4700 */
4701
4702 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4703 int optnum;
4704
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004705 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4706 if (curproxy->options & cfg_opts[optnum].val)
4707 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004708
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004709 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4710 if (curproxy->options2 & cfg_opts2[optnum].val)
4711 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004712 }
4713
Willy Tarreaubb925012009-07-23 13:36:36 +02004714 if (cfgerr > 0)
4715 err_code |= ERR_ALERT | ERR_FATAL;
4716 out:
4717 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718}
4719
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004720/*
4721 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4722 * parsing sessions.
4723 */
4724void cfg_register_keywords(struct cfg_kw_list *kwl)
4725{
4726 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4727}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004729/*
4730 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4731 */
4732void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4733{
4734 LIST_DEL(&kwl->list);
4735 LIST_INIT(&kwl->list);
4736}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737
4738/*
4739 * Local variables:
4740 * c-indent-level: 8
4741 * c-basic-offset: 8
4742 * End:
4743 */