blob: af27d9811f77bc47b52c34b1a3f810180b792713 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020045#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010046#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
56#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010057#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010059#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010061#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062
63
Willy Tarreauf3c69202006-07-09 16:42:34 +020064/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
65 * ssl-hello-chk option to ensure that the remote server speaks SSL.
66 *
67 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
68 */
69const char sslv3_client_hello_pkt[] = {
70 "\x16" /* ContentType : 0x16 = Hanshake */
71 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
72 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
73 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
74 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
75 "\x03\x00" /* Hello Version : 0x0300 = v3 */
76 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
77 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
78 "\x00" /* Session ID length : empty (no session ID) */
79 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
80 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
81 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
82 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
83 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
84 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
85 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
86 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
87 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
88 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
89 "\x00\x38" "\x00\x39" "\x00\x3A"
90 "\x01" /* Compression Length : 0x01 = 1 byte for types */
91 "\x00" /* Compression Type : 0x00 = NULL compression */
92};
93
Willy Tarreau3842f002009-06-14 11:39:52 +020094/* various keyword modifiers */
95enum kw_mod {
96 KWM_STD = 0, /* normal */
97 KWM_NO, /* "no" prefixed before the keyword */
98 KWM_DEF, /* "default" prefixed before the keyword */
99};
100
Willy Tarreau13943ab2006-12-31 00:24:10 +0100101/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100102struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103 const char *name;
104 unsigned int val;
105 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100106 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100107 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100108};
109
110/* proxy->options */
111static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100112{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100113 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
114 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
115 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
116 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
117 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
118 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
119 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
120 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
123 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
125 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
126 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
127 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
128 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100129#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100130 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100131#endif
132
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100134};
135
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136/* proxy->options2 */
137static const struct cfg_opt cfg_opts2[] =
138{
139#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
141 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
142 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
145 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
146 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
147 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
148 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
149 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
150 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
151 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
152 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200154 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100155 { NULL, 0, 0, 0 }
156};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200157
Willy Tarreau6daf3432008-01-22 16:44:08 +0100158static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
160int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100161int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200162
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200163/* List head of all known configuration keywords */
164static struct cfg_kw_list cfg_keywords = {
165 .list = LIST_HEAD_INIT(cfg_keywords.list)
166};
167
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168/*
169 * converts <str> to a list of listeners which are dynamically allocated.
170 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
171 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
172 * - <port> is a numerical port from 1 to 65535 ;
173 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
174 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200175 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200177static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178{
179 struct listener *l;
180 char *c, *next, *range, *dupstr;
181 int port, end;
182
183 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 while (next && *next) {
186 struct sockaddr_storage ss;
187
188 str = next;
189 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100190 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 *next++ = 0;
192 }
193
194 /* 2) look for the addr/port delimiter, it's the last colon. */
195 if ((range = strrchr(str, ':')) == NULL) {
196 Alert("Missing port number: '%s'\n", str);
197 goto fail;
198 }
199
200 *range++ = 0;
201
202 if (strrchr(str, ':') != NULL) {
203 /* IPv6 address contains ':' */
204 memset(&ss, 0, sizeof(ss));
205 ss.ss_family = AF_INET6;
206
207 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
208 Alert("Invalid server address: '%s'\n", str);
209 goto fail;
210 }
211 }
212 else {
213 memset(&ss, 0, sizeof(ss));
214 ss.ss_family = AF_INET;
215
216 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
217 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
218 }
219 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
220 struct hostent *he;
221
222 if ((he = gethostbyname(str)) == NULL) {
223 Alert("Invalid server name: '%s'\n", str);
224 goto fail;
225 }
226 else
227 ((struct sockaddr_in *)&ss)->sin_addr =
228 *(struct in_addr *) *(he->h_addr_list);
229 }
230 }
231
232 /* 3) look for the port-end delimiter */
233 if ((c = strchr(range, '-')) != NULL) {
234 *c++ = 0;
235 end = atol(c);
236 }
237 else {
238 end = atol(range);
239 }
240
241 port = atol(range);
242
243 if (port < 1 || port > 65535) {
244 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
245 goto fail;
246 }
247
248 if (end < 1 || end > 65535) {
249 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
250 goto fail;
251 }
252
253 for (; port <= end; port++) {
254 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200255 l->next = curproxy->listen;
256 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
258 l->fd = -1;
259 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100260 l->state = LI_INIT;
261
262 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv6_add_listener(l);
265 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 tcpv4_add_listener(l);
268 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269
Willy Tarreaue6b98942007-10-29 01:09:36 +0100270 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 } /* end for(port) */
272 } /* end while(next) */
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 fail:
276 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200277 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278}
279
Willy Tarreau977b8e42006-12-29 14:19:17 +0100280/*
281 * Sends a warning if proxy <proxy> does not have at least one of the
282 * capabilities in <cap>. An optionnal <hint> may be added at the end
283 * of the warning to help the user. Returns 1 if a warning was emitted
284 * or 0 if the condition is valid.
285 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100286int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100287{
288 char *msg;
289
290 switch (cap) {
291 case PR_CAP_BE: msg = "no backend"; break;
292 case PR_CAP_FE: msg = "no frontend"; break;
293 case PR_CAP_RS: msg = "no ruleset"; break;
294 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
295 default: msg = "not enough"; break;
296 }
297
298 if (!(proxy->cap & cap)) {
299 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100300 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301 return 1;
302 }
303 return 0;
304}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305
Willy Tarreau61d18892009-03-31 10:49:21 +0200306/* Report a warning if a rule is placed after a 'block' rule.
307 * Return 1 if the warning has been emitted, otherwise 0.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200310{
311 if (!LIST_ISEMPTY(&proxy->block_cond)) {
312 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
313 file, line, arg);
314 return 1;
315 }
316 return 0;
317}
318
319/* Report a warning if a rule is placed after a reqrewrite rule.
320 * Return 1 if the warning has been emitted, otherwise 0.
321 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100322int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200323{
324 if (proxy->req_exp) {
325 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
326 file, line, arg);
327 return 1;
328 }
329 return 0;
330}
331
332/* Report a warning if a rule is placed after a reqadd rule.
333 * Return 1 if the warning has been emitted, otherwise 0.
334 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100335int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200336{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100337 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200338 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
339 file, line, arg);
340 return 1;
341 }
342 return 0;
343}
344
345/* Report a warning if a rule is placed after a redirect rule.
346 * Return 1 if the warning has been emitted, otherwise 0.
347 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100348int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200349{
350 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
351 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
352 file, line, arg);
353 return 1;
354 }
355 return 0;
356}
357
358/* Report a warning if a rule is placed after a 'use_backend' rule.
359 * Return 1 if the warning has been emitted, otherwise 0.
360 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100361int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200362{
363 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
364 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
365 file, line, arg);
366 return 1;
367 }
368 return 0;
369}
370
371/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100372int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200373{
374 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
375 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 reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100381int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200382{
383 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
384 warnif_rule_after_redirect(proxy, file, line, arg) ||
385 warnif_rule_after_use_backend(proxy, file, line, arg);
386}
387
388/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 return warnif_rule_after_redirect(proxy, file, line, arg) ||
392 warnif_rule_after_use_backend(proxy, file, line, arg);
393}
394
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100395/* Report it if a request ACL condition uses some response-only parameters. It
396 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
397 * Note that <cond> may be NULL and then will be ignored.
398 */
399static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
400{
401 struct acl *acl;
402
403 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
404 return 0;
405
406 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
407 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
408 file, line, acl ? acl->name : "(unknown)");
409 return ERR_WARN;
410}
411
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100412/* Report it if a request ACL condition uses some request-only volatile parameters.
413 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
414 * Note that <cond> may be NULL and then will be ignored.
415 */
416static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
417{
418 struct acl *acl;
419
420 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
421 return 0;
422
423 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
424 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
425 file, line, acl ? acl->name : "(unknown)");
426 return ERR_WARN;
427}
428
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100429
Willy Tarreaubaaee002006-06-26 02:48:02 +0200430/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200431 * parse a line in a <global> section. Returns the error code, 0 if OK, or
432 * any combination of :
433 * - ERR_ABORT: must abort ASAP
434 * - ERR_FATAL: we can continue parsing but not start the service
435 * - ERR_WARN: a warning has been emitted
436 * - ERR_ALERT: an alert has been emitted
437 * Only the two first ones can stop processing, the two others are just
438 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200439 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200440int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441{
Willy Tarreau058e9072009-07-20 09:30:05 +0200442 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443
444 if (!strcmp(args[0], "global")) { /* new section */
445 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200447 }
448 else if (!strcmp(args[0], "daemon")) {
449 global.mode |= MODE_DAEMON;
450 }
451 else if (!strcmp(args[0], "debug")) {
452 global.mode |= MODE_DEBUG;
453 }
454 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200457 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
460 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100464 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100466 else if (!strcmp(args[0], "nosplice")) {
467 global.tune.options &= ~GTUNE_USE_SPLICE;
468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 else if (!strcmp(args[0], "quiet")) {
470 global.mode |= MODE_QUIET;
471 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200472 else if (!strcmp(args[0], "tune.maxpollevents")) {
473 if (global.tune.maxpollevents != 0) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200475 err_code |= ERR_ALERT;
476 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200482 }
483 global.tune.maxpollevents = atol(args[1]);
484 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100485 else if (!strcmp(args[0], "tune.maxaccept")) {
486 if (global.tune.maxaccept != 0) {
487 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200488 err_code |= ERR_ALERT;
489 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 err_code |= ERR_ALERT | ERR_FATAL;
494 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100495 }
496 global.tune.maxaccept = atol(args[1]);
497 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200498 else if (!strcmp(args[0], "tune.bufsize")) {
499 if (*(args[1]) == 0) {
500 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
501 err_code |= ERR_ALERT | ERR_FATAL;
502 goto out;
503 }
504 global.tune.bufsize = atol(args[1]);
505 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
506 global.tune.maxrewrite = global.tune.bufsize / 2;
507 }
508 else if (!strcmp(args[0], "tune.maxrewrite")) {
509 if (*(args[1]) == 0) {
510 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
511 err_code |= ERR_ALERT | ERR_FATAL;
512 goto out;
513 }
514 global.tune.maxrewrite = atol(args[1]);
515 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
516 global.tune.maxrewrite = global.tune.bufsize / 2;
517 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100518 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
519 if (global.tune.client_rcvbuf != 0) {
520 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT;
522 goto out;
523 }
524 if (*(args[1]) == 0) {
525 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 global.tune.client_rcvbuf = atol(args[1]);
530 }
531 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
532 if (global.tune.server_rcvbuf != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT;
535 goto out;
536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
541 }
542 global.tune.server_rcvbuf = atol(args[1]);
543 }
544 else if (!strcmp(args[0], "tune.sndbuf.client")) {
545 if (global.tune.client_sndbuf != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
547 err_code |= ERR_ALERT;
548 goto out;
549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
554 }
555 global.tune.client_sndbuf = atol(args[1]);
556 }
557 else if (!strcmp(args[0], "tune.sndbuf.server")) {
558 if (global.tune.server_sndbuf != 0) {
559 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT;
561 goto out;
562 }
563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.server_sndbuf = atol(args[1]);
569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570 else if (!strcmp(args[0], "uid")) {
571 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200572 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200573 err_code |= ERR_ALERT;
574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 }
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 Tarreaubaaee002006-06-26 02:48:02 +0200580 }
581 global.uid = atol(args[1]);
582 }
583 else if (!strcmp(args[0], "gid")) {
584 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200585 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
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.gid = atol(args[1]);
595 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200596 /* user/group name handling */
597 else if (!strcmp(args[0], "user")) {
598 struct passwd *ha_user;
599 if (global.uid != 0) {
600 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200601 err_code |= ERR_ALERT;
602 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200603 }
604 errno = 0;
605 ha_user = getpwnam(args[1]);
606 if (ha_user != NULL) {
607 global.uid = (int)ha_user->pw_uid;
608 }
609 else {
610 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 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200612 }
613 }
614 else if (!strcmp(args[0], "group")) {
615 struct group *ha_group;
616 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200617 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT;
619 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 }
621 errno = 0;
622 ha_group = getgrnam(args[1]);
623 if (ha_group != NULL) {
624 global.gid = (int)ha_group->gr_gid;
625 }
626 else {
627 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 +0200628 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200629 }
630 }
631 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 else if (!strcmp(args[0], "nbproc")) {
633 if (global.nbproc != 0) {
634 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT;
636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 }
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 }
643 global.nbproc = atol(args[1]);
644 }
645 else if (!strcmp(args[0], "maxconn")) {
646 if (global.maxconn != 0) {
647 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT;
649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 }
651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655 }
656 global.maxconn = atol(args[1]);
657#ifdef SYSTEM_MAXCONN
658 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
659 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);
660 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200661 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663#endif /* SYSTEM_MAXCONN */
664 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100665 else if (!strcmp(args[0], "maxpipes")) {
666 if (global.maxpipes != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100675 }
676 global.maxpipes = atol(args[1]);
677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 else if (!strcmp(args[0], "ulimit-n")) {
679 if (global.rlimit_nofile != 0) {
680 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 global.rlimit_nofile = atol(args[1]);
690 }
691 else if (!strcmp(args[0], "chroot")) {
692 if (global.chroot != NULL) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.chroot = strdup(args[1]);
703 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200704 else if (!strcmp(args[0], "description")) {
705 int i, len=0;
706 char *d;
707
708 if (!*args[1]) {
709 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
710 file, linenum, args[0]);
711 err_code |= ERR_ALERT | ERR_FATAL;
712 goto out;
713 }
714
715 for(i=1; *args[i]; i++)
716 len += strlen(args[i])+1;
717
718 if (global.desc)
719 free(global.desc);
720
721 global.desc = d = (char *)calloc(1, len);
722
723 d += sprintf(d, "%s", args[1]);
724 for(i=2; *args[i]; i++)
725 d += sprintf(d, " %s", args[i]);
726 }
727 else if (!strcmp(args[0], "node")) {
728 int i;
729 char c;
730
731 for (i=0; args[1][i]; i++) {
732 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100733 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
734 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200735 break;
736 }
737
738 if (!i || args[1][i]) {
739 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
740 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
741 file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745
746 if (global.node)
747 free(global.node);
748
749 global.node = strdup(args[1]);
750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 else if (!strcmp(args[0], "pidfile")) {
752 if (global.pidfile != NULL) {
753 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200754 err_code |= ERR_ALERT;
755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 }
757 if (*(args[1]) == 0) {
758 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761 }
762 global.pidfile = strdup(args[1]);
763 }
764 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100765 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200766 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767
768 if (*(args[1]) == 0 || *(args[2]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 }
773
774 facility = get_log_facility(args[2]);
775 if (facility < 0) {
776 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200777 err_code |= ERR_ALERT | ERR_FATAL;
778 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 }
780
781 level = 7; /* max syslog level = debug */
782 if (*(args[3])) {
783 level = get_log_level(args[3]);
784 if (level < 0) {
785 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200786 err_code |= ERR_ALERT | ERR_FATAL;
787 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788 }
789 }
790
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200791 minlvl = 0; /* limit syslog level to this level (emerg) */
792 if (*(args[4])) {
793 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200794 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200795 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200796 err_code |= ERR_ALERT | ERR_FATAL;
797 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200798 }
799 }
800
Robert Tsai81ae1952007-12-05 10:47:29 +0100801 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100802 struct sockaddr_un *sk = str2sun(args[1]);
803 if (!sk) {
804 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
805 args[1], (int)sizeof(sk->sun_path) - 1);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100810 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100811 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100812 struct sockaddr_in *sk = str2sa(args[1]);
813 if (!sk) {
814 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100819 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100820 if (!logsrv.u.in.sin_port)
821 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823
824 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100825 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 global.logfac1 = facility;
827 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200828 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 }
830 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100831 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 global.logfac2 = facility;
833 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200834 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
836 else {
837 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200840 }
841 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
842 if (global.spread_checks != 0) {
843 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200844 err_code |= ERR_ALERT;
845 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200846 }
847 if (*(args[1]) == 0) {
848 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200851 }
852 global.spread_checks = atol(args[1]);
853 if (global.spread_checks < 0 || global.spread_checks > 50) {
854 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200855 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200859 struct cfg_kw_list *kwl;
860 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200861 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200862
863 list_for_each_entry(kwl, &cfg_keywords.list, list) {
864 for (index = 0; kwl->kw[index].kw != NULL; index++) {
865 if (kwl->kw[index].section != CFG_GLOBAL)
866 continue;
867 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
868 /* prepare error message just in case */
869 snprintf(trash, sizeof(trash),
870 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200871 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
872 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200873 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200874 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200875 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200876 else if (rc > 0) {
877 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200878 err_code |= ERR_WARN;
879 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200880 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200881 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200882 }
883 }
884 }
885
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200889
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 out:
891 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892}
893
Willy Tarreau97cb7802010-01-03 20:23:58 +0100894/* Perform the most basic initialization of a proxy :
895 * memset(), list_init(*), reset_timeouts(*).
896 */
897static void init_new_proxy(struct proxy *p)
898{
899 memset(p, 0, sizeof(struct proxy));
900 LIST_INIT(&p->pendconns);
901 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100902 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100903 LIST_INIT(&p->block_cond);
904 LIST_INIT(&p->redirect_rules);
905 LIST_INIT(&p->mon_fail_cond);
906 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +0200907 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100908 LIST_INIT(&p->sticking_rules);
909 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100910 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +0200911 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100912 LIST_INIT(&p->req_add);
913 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100914
915 /* Timeouts are defined as -1 */
916 proxy_reset_timeouts(p);
917}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200919void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100921 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 defproxy.mode = PR_MODE_TCP;
923 defproxy.state = PR_STNEW;
924 defproxy.maxconn = cfg_maxpconn;
925 defproxy.conn_retries = CONN_RETRIES;
926 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100927
928 defproxy.defsrv.inter = DEF_CHKINTR;
929 defproxy.defsrv.fastinter = 0;
930 defproxy.defsrv.downinter = 0;
931 defproxy.defsrv.rise = DEF_RISETIME;
932 defproxy.defsrv.fall = DEF_FALLTIME;
933 defproxy.defsrv.check_port = 0;
934 defproxy.defsrv.maxqueue = 0;
935 defproxy.defsrv.minconn = 0;
936 defproxy.defsrv.maxconn = 0;
937 defproxy.defsrv.slowstart = 0;
938 defproxy.defsrv.onerror = DEF_HANA_ONERR;
939 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
940 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941}
942
Willy Tarreauade5ec42010-01-28 19:33:49 +0100943
944static int create_cond_regex_rule(const char *file, int line,
945 struct proxy *px, int dir, int action, int flags,
946 const char *cmd, const char *reg, const char *repl,
947 const char **cond_start)
948{
949 regex_t *preg = NULL;
950 const char *err;
951 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100952 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100953
954 if (px == &defproxy) {
955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto err;
958 }
959
960 if (*reg == 0) {
961 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto err;
964 }
965
966 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
967 err_code |= ERR_WARN;
968
Willy Tarreau5321c422010-01-28 20:35:13 +0100969 if (cond_start &&
970 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
971 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
972 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
973 file, line, cmd);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto err;
976 }
977 }
978 else if (cond_start && **cond_start) {
979 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
980 file, line, cmd, *cond_start);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto err;
983 }
984
985 if (dir == ACL_DIR_REQ)
986 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100987 else
988 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100989
Willy Tarreauade5ec42010-01-28 19:33:49 +0100990 preg = calloc(1, sizeof(regex_t));
991 if (!preg) {
992 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
993 err_code = ERR_ALERT | ERR_FATAL;
994 goto err;
995 }
996
997 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
998 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
999 err_code = ERR_ALERT | ERR_FATAL;
1000 goto err;
1001 }
1002
1003 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001004 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001005 if (repl && err) {
1006 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1007 file, line, cmd, *err);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto err;
1010 }
1011
1012 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1013 err_code |= ERR_WARN;
1014
1015 return err_code;
1016 err:
1017 free(preg);
1018 return err_code;
1019}
1020
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001023 * Returns the error code, 0 if OK, or any combination of :
1024 * - ERR_ABORT: must abort ASAP
1025 * - ERR_FATAL: we can continue parsing but not start the service
1026 * - ERR_WARN: a warning has been emitted
1027 * - ERR_ALERT: an alert has been emitted
1028 * Only the two first ones can stop processing, the two others are just
1029 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001031int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032{
1033 static struct proxy *curproxy = NULL;
1034 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001035 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001036 int rc;
1037 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001038 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001039 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040
Willy Tarreau977b8e42006-12-29 14:19:17 +01001041 if (!strcmp(args[0], "listen"))
1042 rc = PR_CAP_LISTEN;
1043 else if (!strcmp(args[0], "frontend"))
1044 rc = PR_CAP_FE | PR_CAP_RS;
1045 else if (!strcmp(args[0], "backend"))
1046 rc = PR_CAP_BE | PR_CAP_RS;
1047 else if (!strcmp(args[0], "ruleset"))
1048 rc = PR_CAP_RS;
1049 else
1050 rc = PR_CAP_NONE;
1051
1052 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 if (!*args[1]) {
1054 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1055 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1056 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001057 err_code |= ERR_ALERT | ERR_ABORT;
1058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001060
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001061 err = invalid_char(args[1]);
1062 if (err) {
1063 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1064 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001065 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001066 }
1067
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001068 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1069 /*
1070 * If there are two proxies with the same name only following
1071 * combinations are allowed:
1072 *
1073 * listen backend frontend ruleset
1074 * listen - - - -
1075 * backend - - OK -
1076 * frontend - OK - -
1077 * ruleset - - - -
1078 */
1079
1080 if (!strcmp(curproxy->id, args[1]) &&
1081 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1082 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001083 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1084 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1085 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001086 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001087 }
1088 }
1089
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1091 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001092 err_code |= ERR_ALERT | ERR_ABORT;
1093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001095
Willy Tarreau97cb7802010-01-03 20:23:58 +01001096 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 curproxy->next = proxy;
1098 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001099 curproxy->conf.file = file;
1100 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001101 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001103 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104
1105 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001106 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001107 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001108 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001109 err_code |= ERR_FATAL;
1110 goto out;
1111 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001112 new = curproxy->listen;
1113 while (new != last) {
1114 new->conf.file = file;
1115 new->conf.line = linenum;
1116 new = new->next;
1117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001118 global.maxsock++;
1119 }
1120
1121 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001122 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001123 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001127 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001128 curproxy->no_options = defproxy.no_options;
1129 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001130 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001131 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001132 curproxy->except_net = defproxy.except_net;
1133 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001134 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001135 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001137 if (defproxy.fwdfor_hdr_len) {
1138 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1139 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1140 }
1141
Willy Tarreaub86db342009-11-30 11:50:16 +01001142 if (defproxy.orgto_hdr_len) {
1143 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1144 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1145 }
1146
Willy Tarreau977b8e42006-12-29 14:19:17 +01001147 if (curproxy->cap & PR_CAP_FE) {
1148 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001149 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001150 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001151
1152 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001153 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1154 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001155
1156 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158
Willy Tarreau977b8e42006-12-29 14:19:17 +01001159 if (curproxy->cap & PR_CAP_BE) {
1160 curproxy->fullconn = defproxy.fullconn;
1161 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162
Willy Tarreau977b8e42006-12-29 14:19:17 +01001163 if (defproxy.check_req)
1164 curproxy->check_req = strdup(defproxy.check_req);
1165 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166
Willy Tarreau977b8e42006-12-29 14:19:17 +01001167 if (defproxy.cookie_name)
1168 curproxy->cookie_name = strdup(defproxy.cookie_name);
1169 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001170 if (defproxy.cookie_domain)
1171 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001172
Emeric Brun647caf12009-06-30 17:57:00 +02001173 if (defproxy.rdp_cookie_name)
1174 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1175 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1176
Willy Tarreau01732802007-11-01 22:48:15 +01001177 if (defproxy.url_param_name)
1178 curproxy->url_param_name = strdup(defproxy.url_param_name);
1179 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001180
Benoitaffb4812009-03-25 13:02:10 +01001181 if (defproxy.hh_name)
1182 curproxy->hh_name = strdup(defproxy.hh_name);
1183 curproxy->hh_len = defproxy.hh_len;
1184 curproxy->hh_match_domain = defproxy.hh_match_domain;
1185
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001186 if (defproxy.iface_name)
1187 curproxy->iface_name = strdup(defproxy.iface_name);
1188 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001191 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001192 if (defproxy.capture_name)
1193 curproxy->capture_name = strdup(defproxy.capture_name);
1194 curproxy->capture_namelen = defproxy.capture_namelen;
1195 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001199 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001200 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001201 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001202 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001203 curproxy->uri_auth = defproxy.uri_auth;
1204 curproxy->mon_net = defproxy.mon_net;
1205 curproxy->mon_mask = defproxy.mon_mask;
1206 if (defproxy.monitor_uri)
1207 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1208 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001209 if (defproxy.defbe.name)
1210 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001211 }
1212
1213 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001214 curproxy->timeout.connect = defproxy.timeout.connect;
1215 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001216 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001217 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001218 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001219 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001220 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001221 curproxy->source_addr = defproxy.source_addr;
1222 }
1223
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 curproxy->mode = defproxy.mode;
1225 curproxy->logfac1 = defproxy.logfac1;
1226 curproxy->logsrv1 = defproxy.logsrv1;
1227 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001228 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 curproxy->logfac2 = defproxy.logfac2;
1230 curproxy->logsrv2 = defproxy.logsrv2;
1231 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001232 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001234 curproxy->conf.used_listener_id = EB_ROOT;
1235 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001236
Willy Tarreau93893792009-07-23 13:19:11 +02001237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001238 }
1239 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1240 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001241 /* FIXME-20070101: we should do this too at the end of the
1242 * config parsing to free all default values.
1243 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001244 free(defproxy.check_req);
1245 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001246 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001247 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001248 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001249 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001250 free(defproxy.capture_name);
1251 free(defproxy.monitor_uri);
1252 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001253 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001254 free(defproxy.fwdfor_hdr_name);
1255 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001256 free(defproxy.orgto_hdr_name);
1257 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001258
Willy Tarreaua534fea2008-08-03 12:19:50 +02001259 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001260 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001261
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 /* we cannot free uri_auth because it might already be used */
1263 init_default_instance();
1264 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001265 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268 else if (curproxy == NULL) {
1269 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 }
1273
Willy Tarreau977b8e42006-12-29 14:19:17 +01001274
1275 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001276 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001277 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001278 int cur_arg;
1279
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 if (curproxy == &defproxy) {
1281 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001285 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001286 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287
1288 if (strchr(args[1], ':') == NULL) {
1289 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1290 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001294
1295 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001296 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
1299 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001300
Willy Tarreau90a570f2009-10-04 20:54:54 +02001301 new_listen = curproxy->listen;
1302 while (new_listen != last_listen) {
1303 new_listen->conf.file = file;
1304 new_listen->conf.line = linenum;
1305 new_listen = new_listen->next;
1306 }
1307
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001308 cur_arg = 2;
1309 while (*(args[cur_arg])) {
1310 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1311#ifdef SO_BINDTODEVICE
1312 struct listener *l;
1313
1314 if (!*args[cur_arg + 1]) {
1315 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1316 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001319 }
1320
1321 for (l = curproxy->listen; l != last_listen; l = l->next)
1322 l->interface = strdup(args[cur_arg + 1]);
1323
1324 global.last_checks |= LSTCHK_NETADM;
1325
1326 cur_arg += 2;
1327 continue;
1328#else
1329 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1330 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001333#endif
1334 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001335 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1336#ifdef TCP_MAXSEG
1337 struct listener *l;
1338 int mss;
1339
1340 if (!*args[cur_arg + 1]) {
1341 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001345 }
1346
1347 mss = str2uic(args[cur_arg + 1]);
1348 if (mss < 1 || mss > 65535) {
1349 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1350 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001353 }
1354
1355 for (l = curproxy->listen; l != last_listen; l = l->next)
1356 l->maxseg = mss;
1357
1358 cur_arg += 2;
1359 continue;
1360#else
1361 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1362 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001365#endif
1366 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001367
1368 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1369#ifdef TCP_DEFER_ACCEPT
1370 struct listener *l;
1371
1372 for (l = curproxy->listen; l != last_listen; l = l->next)
1373 l->options |= LI_O_DEF_ACCEPT;
1374
1375 cur_arg ++;
1376 continue;
1377#else
1378 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1379 file, linenum, args[0], args[cur_arg]);
1380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
1382#endif
1383 }
1384
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001385 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001386#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001387 struct listener *l;
1388
1389 for (l = curproxy->listen; l != last_listen; l = l->next)
1390 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001391
1392 cur_arg ++;
1393 continue;
1394#else
1395 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1396 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001399#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001400 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001401
1402 if (!strcmp(args[cur_arg], "name")) {
1403 struct listener *l;
1404
1405 for (l = curproxy->listen; l != last_listen; l = l->next)
1406 l->name = strdup(args[cur_arg + 1]);
1407
1408 cur_arg += 2;
1409 continue;
1410 }
1411
1412 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001413 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001414 struct listener *l;
1415
1416 if (curproxy->listen->next != last_listen) {
1417 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1418 file, linenum, args[cur_arg]);
1419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
1421 }
1422
1423 if (!*args[cur_arg + 1]) {
1424 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1425 file, linenum, args[cur_arg]);
1426 err_code |= ERR_ALERT | ERR_FATAL;
1427 goto out;
1428 }
1429
1430 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001431 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001432
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001433 if (curproxy->listen->luid <= 0) {
1434 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001435 file, linenum);
1436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
1438 }
1439
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001440 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1441 if (node) {
1442 l = container_of(node, struct listener, conf.id);
1443 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1444 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
1448 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1449
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001450 cur_arg += 2;
1451 continue;
1452 }
1453
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001454 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 +01001455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001456 err_code |= ERR_ALERT | ERR_FATAL;
1457 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 }
1462 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1463 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1464 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1465 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001470 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 /* flush useless bits */
1473 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001476 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001477 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001478 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479
Willy Tarreau1c47f852006-07-09 08:22:27 +02001480 if (!*args[1]) {
1481 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001485 }
1486
Willy Tarreaua534fea2008-08-03 12:19:50 +02001487 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001488 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001489 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001490 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001491 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1492
Willy Tarreau93893792009-07-23 13:19:11 +02001493 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1496 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1497 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1498 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1499 else {
1500 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001501 err_code |= ERR_ALERT | ERR_FATAL;
1502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001503 }
1504 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001505 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001506 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001507
1508 if (curproxy == &defproxy) {
1509 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1510 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001513 }
1514
1515 if (!*args[1]) {
1516 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1517 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001520 }
1521
1522 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001523 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001524
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001525 if (curproxy->uuid <= 0) {
1526 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001530 }
1531
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001532 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1533 if (node) {
1534 struct proxy *target = container_of(node, struct proxy, conf.id);
1535 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1536 file, linenum, proxy_type_str(curproxy), curproxy->id,
1537 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
1541 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001542 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001543 else if (!strcmp(args[0], "description")) {
1544 int i, len=0;
1545 char *d;
1546
Cyril Bonté99ed3272010-01-24 23:29:44 +01001547 if (curproxy == &defproxy) {
1548 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1549 file, linenum, args[0]);
1550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
1552 }
1553
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001554 if (!*args[1]) {
1555 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1556 file, linenum, args[0]);
1557 return -1;
1558 }
1559
1560 for(i=1; *args[i]; i++)
1561 len += strlen(args[i])+1;
1562
1563 d = (char *)calloc(1, len);
1564 curproxy->desc = d;
1565
1566 d += sprintf(d, "%s", args[1]);
1567 for(i=2; *args[i]; i++)
1568 d += sprintf(d, " %s", args[i]);
1569
1570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1572 curproxy->state = PR_STSTOPPED;
1573 }
1574 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1575 curproxy->state = PR_STNEW;
1576 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001577 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1578 int cur_arg = 1;
1579 unsigned int set = 0;
1580
1581 while (*args[cur_arg]) {
1582 int u;
1583 if (strcmp(args[cur_arg], "all") == 0) {
1584 set = 0;
1585 break;
1586 }
1587 else if (strcmp(args[cur_arg], "odd") == 0) {
1588 set |= 0x55555555;
1589 }
1590 else if (strcmp(args[cur_arg], "even") == 0) {
1591 set |= 0xAAAAAAAA;
1592 }
1593 else {
1594 u = str2uic(args[cur_arg]);
1595 if (u < 1 || u > 32) {
1596 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001598 err_code |= ERR_ALERT | ERR_FATAL;
1599 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001600 }
1601 if (u > global.nbproc) {
1602 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001605 }
1606 set |= 1 << (u - 1);
1607 }
1608 cur_arg++;
1609 }
1610 curproxy->bind_proc = set;
1611 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001612 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001613 if (curproxy == &defproxy) {
1614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001617 }
1618
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001619 err = invalid_char(args[1]);
1620 if (err) {
1621 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1622 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001624 }
1625
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001626 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1627 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1628 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001631 }
1632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1634 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635
Willy Tarreau977b8e42006-12-29 14:19:17 +01001636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001638
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 if (*(args[1]) == 0) {
1640 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001645
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001646 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001647 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 curproxy->cookie_name = strdup(args[1]);
1649 curproxy->cookie_len = strlen(curproxy->cookie_name);
1650
1651 cur_arg = 2;
1652 while (*(args[cur_arg])) {
1653 if (!strcmp(args[cur_arg], "rewrite")) {
1654 curproxy->options |= PR_O_COOK_RW;
1655 }
1656 else if (!strcmp(args[cur_arg], "indirect")) {
1657 curproxy->options |= PR_O_COOK_IND;
1658 }
1659 else if (!strcmp(args[cur_arg], "insert")) {
1660 curproxy->options |= PR_O_COOK_INS;
1661 }
1662 else if (!strcmp(args[cur_arg], "nocache")) {
1663 curproxy->options |= PR_O_COOK_NOC;
1664 }
1665 else if (!strcmp(args[cur_arg], "postonly")) {
1666 curproxy->options |= PR_O_COOK_POST;
1667 }
1668 else if (!strcmp(args[cur_arg], "prefix")) {
1669 curproxy->options |= PR_O_COOK_PFX;
1670 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001671 else if (!strcmp(args[cur_arg], "domain")) {
1672 if (!*args[cur_arg + 1]) {
1673 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1674 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001677 }
1678
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001679 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001680 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001681 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1682 " dots nor does not start with a dot."
1683 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001684 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001685 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001686 }
1687
1688 err = invalid_domainchar(args[cur_arg + 1]);
1689 if (err) {
1690 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1691 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001692 err_code |= ERR_ALERT | ERR_FATAL;
1693 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001694 }
1695
Willy Tarreau68a897b2009-12-03 23:28:34 +01001696 if (!curproxy->cookie_domain) {
1697 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1698 } else {
1699 /* one domain was already specified, add another one by
1700 * building the string which will be returned along with
1701 * the cookie.
1702 */
1703 char *new_ptr;
1704 int new_len = strlen(curproxy->cookie_domain) +
1705 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1706 new_ptr = malloc(new_len);
1707 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1708 free(curproxy->cookie_domain);
1709 curproxy->cookie_domain = new_ptr;
1710 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001711 cur_arg++;
1712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001714 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 }
1719 cur_arg++;
1720 }
1721 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1722 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1723 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001724 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 }
1726
1727 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1728 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1729 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 }
1732 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001733 else if (!strcmp(args[0], "persist")) { /* persist */
1734 if (*(args[1]) == 0) {
1735 Alert("parsing [%s:%d] : missing persist method.\n",
1736 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001739 }
1740
1741 if (!strncmp(args[1], "rdp-cookie", 10)) {
1742 curproxy->options2 |= PR_O2_RDPC_PRST;
1743
Emeric Brunb982a3d2010-01-04 15:45:53 +01001744 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001745 const char *beg, *end;
1746
1747 beg = args[1] + 11;
1748 end = strchr(beg, ')');
1749
1750 if (!end || end == beg) {
1751 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1752 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001755 }
1756
1757 free(curproxy->rdp_cookie_name);
1758 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1759 curproxy->rdp_cookie_len = end-beg;
1760 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001761 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001762 free(curproxy->rdp_cookie_name);
1763 curproxy->rdp_cookie_name = strdup("msts");
1764 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1765 }
1766 else { /* syntax */
1767 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1768 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001771 }
1772 }
1773 else {
1774 Alert("parsing [%s:%d] : unknown persist method.\n",
1775 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001778 }
1779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001781 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001782
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001783 if (curproxy == &defproxy) {
1784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001793 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_FATAL;
1796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
1798 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001799 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 curproxy->appsession_name = strdup(args[1]);
1801 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1802 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001803 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1804 if (err) {
1805 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1806 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001809 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001810 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001811
Willy Tarreau51041c72007-09-09 21:56:53 +02001812 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1813 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001814 err_code |= ERR_ALERT | ERR_ABORT;
1815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001817
1818 cur_arg = 6;
1819 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001820 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1821 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001822 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001823 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001824 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001825 } else if (!strcmp(args[cur_arg], "prefix")) {
1826 curproxy->options2 |= PR_O2_AS_PFX;
1827 } else if (!strcmp(args[cur_arg], "mode")) {
1828 if (!*args[cur_arg + 1]) {
1829 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1830 file, linenum, args[0], args[cur_arg]);
1831 err_code |= ERR_ALERT | ERR_FATAL;
1832 goto out;
1833 }
1834
1835 cur_arg++;
1836 if (!strcmp(args[cur_arg], "query-string")) {
1837 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1838 curproxy->options2 |= PR_O2_AS_M_QS;
1839 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1840 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1841 curproxy->options2 |= PR_O2_AS_M_PP;
1842 } else {
1843 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001848 cur_arg++;
1849 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 } /* Url App Session */
1851 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001852 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001853 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001856 if (curproxy == &defproxy) {
1857 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 if (*(args[4]) == 0) {
1863 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1864 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001867 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001868 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 curproxy->capture_name = strdup(args[2]);
1870 curproxy->capture_namelen = strlen(curproxy->capture_name);
1871 curproxy->capture_len = atol(args[4]);
1872 if (curproxy->capture_len >= CAPTURE_LEN) {
1873 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1874 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001876 curproxy->capture_len = CAPTURE_LEN - 1;
1877 }
1878 curproxy->to_log |= LW_COOKIE;
1879 }
1880 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1881 struct cap_hdr *hdr;
1882
1883 if (curproxy == &defproxy) {
1884 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 +02001885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 }
1888
1889 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1890 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1891 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
1895
1896 hdr = calloc(sizeof(struct cap_hdr), 1);
1897 hdr->next = curproxy->req_cap;
1898 hdr->name = strdup(args[3]);
1899 hdr->namelen = strlen(args[3]);
1900 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001901 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 hdr->index = curproxy->nb_req_cap++;
1903 curproxy->req_cap = hdr;
1904 curproxy->to_log |= LW_REQHDR;
1905 }
1906 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1907 struct cap_hdr *hdr;
1908
1909 if (curproxy == &defproxy) {
1910 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 +02001911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 }
1914
1915 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1916 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1917 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001918 err_code |= ERR_ALERT | ERR_FATAL;
1919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 }
1921 hdr = calloc(sizeof(struct cap_hdr), 1);
1922 hdr->next = curproxy->rsp_cap;
1923 hdr->name = strdup(args[3]);
1924 hdr->namelen = strlen(args[3]);
1925 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001926 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 hdr->index = curproxy->nb_rsp_cap++;
1928 curproxy->rsp_cap = hdr;
1929 curproxy->to_log |= LW_RSPHDR;
1930 }
1931 else {
1932 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 }
1937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001941
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 if (*(args[1]) == 0) {
1943 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001945 err_code |= ERR_ALERT | ERR_FATAL;
1946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 }
1948 curproxy->conn_retries = atol(args[1]);
1949 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001950 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1951 struct req_acl_rule *req_acl;
1952
1953 if (curproxy == &defproxy) {
1954 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
1959
1960 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1961 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1962 file, linenum, args[0]);
1963 err_code |= ERR_WARN;
1964 }
1965
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001966 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001967
1968 if (!req_acl) {
1969 err_code |= ERR_ALERT | ERR_ABORT;
1970 goto out;
1971 }
1972
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001973 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001974 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1975 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001976 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001977 if (curproxy == &defproxy) {
1978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001979 err_code |= ERR_ALERT | ERR_FATAL;
1980 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001981 }
1982
Willy Tarreauef6494c2010-01-28 17:12:36 +01001983 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001984 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1985 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001988 }
1989
Willy Tarreauef6494c2010-01-28 17:12:36 +01001990 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001991 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1992 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001995 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001996
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001997 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001998 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001999 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002000 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002001 struct redirect_rule *rule;
2002 int cur_arg;
2003 int type = REDIRECT_TYPE_NONE;
2004 int code = 302;
2005 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002006 char *cookie = NULL;
2007 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002008 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002009
Cyril Bonté99ed3272010-01-24 23:29:44 +01002010 if (curproxy == &defproxy) {
2011 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
2014 }
2015
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002016 cur_arg = 1;
2017 while (*(args[cur_arg])) {
2018 if (!strcmp(args[cur_arg], "location")) {
2019 if (!*args[cur_arg + 1]) {
2020 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2021 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002022 err_code |= ERR_ALERT | ERR_FATAL;
2023 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002024 }
2025
2026 type = REDIRECT_TYPE_LOCATION;
2027 cur_arg++;
2028 destination = args[cur_arg];
2029 }
2030 else if (!strcmp(args[cur_arg], "prefix")) {
2031 if (!*args[cur_arg + 1]) {
2032 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2033 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002036 }
2037
2038 type = REDIRECT_TYPE_PREFIX;
2039 cur_arg++;
2040 destination = args[cur_arg];
2041 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002042 else if (!strcmp(args[cur_arg], "set-cookie")) {
2043 if (!*args[cur_arg + 1]) {
2044 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2045 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002048 }
2049
2050 cur_arg++;
2051 cookie = args[cur_arg];
2052 cookie_set = 1;
2053 }
2054 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2055 if (!*args[cur_arg + 1]) {
2056 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2057 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002060 }
2061
2062 cur_arg++;
2063 cookie = args[cur_arg];
2064 cookie_set = 0;
2065 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002066 else if (!strcmp(args[cur_arg],"code")) {
2067 if (!*args[cur_arg + 1]) {
2068 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002072 }
2073 cur_arg++;
2074 code = atol(args[cur_arg]);
2075 if (code < 301 || code > 303) {
2076 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2077 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002080 }
2081 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002082 else if (!strcmp(args[cur_arg],"drop-query")) {
2083 flags |= REDIRECT_FLAG_DROP_QS;
2084 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002085 else if (!strcmp(args[cur_arg],"append-slash")) {
2086 flags |= REDIRECT_FLAG_APPEND_SLASH;
2087 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002088 else if (strcmp(args[cur_arg], "if") == 0 ||
2089 strcmp(args[cur_arg], "unless") == 0) {
2090 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2091 if (!cond) {
2092 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2093 file, linenum, args[0]);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002097 break;
2098 }
2099 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002100 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002101 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002104 }
2105 cur_arg++;
2106 }
2107
2108 if (type == REDIRECT_TYPE_NONE) {
2109 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2110 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002111 err_code |= ERR_ALERT | ERR_FATAL;
2112 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002113 }
2114
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002115 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2116 rule->cond = cond;
2117 rule->rdr_str = strdup(destination);
2118 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002119 if (cookie) {
2120 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002121 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002122 */
2123 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002124 if (cookie_set) {
2125 rule->cookie_str = malloc(rule->cookie_len + 10);
2126 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2127 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2128 rule->cookie_len += 9;
2129 } else {
2130 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002131 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002132 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2133 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002134 }
2135 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002136 rule->type = type;
2137 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002138 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002139 LIST_INIT(&rule->list);
2140 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002141 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002142 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002143 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002144 struct switching_rule *rule;
2145
Willy Tarreaub099aca2008-10-12 17:26:37 +02002146 if (curproxy == &defproxy) {
2147 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002150 }
2151
Willy Tarreau55ea7572007-06-17 19:56:27 +02002152 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002153 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002154
2155 if (*(args[1]) == 0) {
2156 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002159 }
2160
Willy Tarreauef6494c2010-01-28 17:12:36 +01002161 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002162 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2163 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002166 }
2167
Willy Tarreauef6494c2010-01-28 17:12:36 +01002168 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002169 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002170 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002171 err_code |= ERR_ALERT | ERR_FATAL;
2172 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002173 }
2174
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002175 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002176
Willy Tarreau55ea7572007-06-17 19:56:27 +02002177 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2178 rule->cond = cond;
2179 rule->be.name = strdup(args[1]);
2180 LIST_INIT(&rule->list);
2181 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2182 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002183 else if ((!strcmp(args[0], "force-persist")) ||
2184 (!strcmp(args[0], "ignore-persist"))) {
2185 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002186
2187 if (curproxy == &defproxy) {
2188 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
2193 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2194 err_code |= ERR_WARN;
2195
Willy Tarreauef6494c2010-01-28 17:12:36 +01002196 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002197 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2198 file, linenum, args[0]);
2199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
2202
Willy Tarreauef6494c2010-01-28 17:12:36 +01002203 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002204 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2205 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
2208 }
2209
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002210 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002211
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002212 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002213 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002214 if (!strcmp(args[0], "force-persist")) {
2215 rule->type = PERSIST_TYPE_FORCE;
2216 } else {
2217 rule->type = PERSIST_TYPE_IGNORE;
2218 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002219 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002220 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002221 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002222 else if (!strcmp(args[0], "stick-table")) {
2223 int myidx = 1;
2224
2225 curproxy->table.type = (unsigned int)-1;
2226 while (*args[myidx]) {
2227 const char *err;
2228
2229 if (strcmp(args[myidx], "size") == 0) {
2230 myidx++;
2231 if (!*(args[myidx])) {
2232 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2233 file, linenum, args[myidx-1]);
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
2237 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2238 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2239 file, linenum, *err, args[myidx-1]);
2240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
2242 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002243 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002244 }
2245 else if (strcmp(args[myidx], "expire") == 0) {
2246 myidx++;
2247 if (!*(args[myidx])) {
2248 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2249 file, linenum, args[myidx-1]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2254 if (err) {
2255 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2256 file, linenum, *err, args[myidx-1]);
2257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
2259 }
2260 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002261 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002262 }
2263 else if (strcmp(args[myidx], "nopurge") == 0) {
2264 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002265 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002266 }
2267 else if (strcmp(args[myidx], "type") == 0) {
2268 myidx++;
2269 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2270 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2271 file, linenum, args[myidx]);
2272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
2274 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002275 /* myidx already points to next arg */
2276 }
2277 else {
2278 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2279 file, linenum, args[myidx]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002282 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002283 }
2284
2285 if (!curproxy->table.size) {
2286 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2287 file, linenum);
2288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291
2292 if (curproxy->table.type == (unsigned int)-1) {
2293 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2294 file, linenum);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298 }
2299 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002300 struct sticking_rule *rule;
2301 struct pattern_expr *expr;
2302 int myidx = 0;
2303 const char *name = NULL;
2304 int flags;
2305
2306 if (curproxy == &defproxy) {
2307 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
2310 }
2311
2312 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2313 err_code |= ERR_WARN;
2314 goto out;
2315 }
2316
2317 myidx++;
2318 if ((strcmp(args[myidx], "store") == 0) ||
2319 (strcmp(args[myidx], "store-request") == 0)) {
2320 myidx++;
2321 flags = STK_IS_STORE;
2322 }
2323 else if (strcmp(args[myidx], "store-response") == 0) {
2324 myidx++;
2325 flags = STK_IS_STORE | STK_ON_RSP;
2326 }
2327 else if (strcmp(args[myidx], "match") == 0) {
2328 myidx++;
2329 flags = STK_IS_MATCH;
2330 }
2331 else if (strcmp(args[myidx], "on") == 0) {
2332 myidx++;
2333 flags = STK_IS_MATCH | STK_IS_STORE;
2334 }
2335 else {
2336 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 if (*(args[myidx]) == 0) {
2342 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346
2347 expr = pattern_parse_expr(args, &myidx);
2348 if (!expr) {
2349 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353
2354 if (flags & STK_ON_RSP) {
2355 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2356 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2357 file, linenum, args[0], expr->fetch->kw);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361 } else {
2362 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2363 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2364 file, linenum, args[0], expr->fetch->kw);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
2367 }
2368 }
2369
2370 if (strcmp(args[myidx], "table") == 0) {
2371 myidx++;
2372 name = args[myidx++];
2373 }
2374
Willy Tarreauef6494c2010-01-28 17:12:36 +01002375 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2376 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002377 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2378 file, linenum, args[0]);
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
2381 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002382 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002383 else if (*(args[myidx])) {
2384 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2385 file, linenum, args[0], args[myidx]);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
2389
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002390 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2391
Emeric Brunb982a3d2010-01-04 15:45:53 +01002392 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2393 rule->cond = cond;
2394 rule->expr = expr;
2395 rule->flags = flags;
2396 rule->table.name = name ? strdup(name) : NULL;
2397 LIST_INIT(&rule->list);
2398 if (flags & STK_ON_RSP)
2399 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2400 else
2401 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2408 curproxy->uri_auth = NULL; /* we must detach from the default config */
2409
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002410 if (!*args[1]) {
2411 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 } else if (!strcmp(args[1], "uri")) {
2413 if (*(args[2]) == 0) {
2414 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2418 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_ABORT;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422 } else if (!strcmp(args[1], "realm")) {
2423 if (*(args[2]) == 0) {
2424 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2428 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_ABORT;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002432 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002433 unsigned interval;
2434
2435 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2436 if (err) {
2437 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2438 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002441 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_ABORT;
2444 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002445 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002446 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2447 struct req_acl_rule *req_acl;
2448
2449 if (curproxy == &defproxy) {
2450 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
2453 }
2454
2455 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2456 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2457 err_code |= ERR_ALERT | ERR_ABORT;
2458 goto out;
2459 }
2460
2461 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2462 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2463 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2464 file, linenum, args[0]);
2465 err_code |= ERR_WARN;
2466 }
2467
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002468 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002469
2470 if (!req_acl) {
2471 err_code |= ERR_ALERT | ERR_ABORT;
2472 goto out;
2473 }
2474
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002475 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002476 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2477
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 } else if (!strcmp(args[1], "auth")) {
2479 if (*(args[2]) == 0) {
2480 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2484 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_ABORT;
2486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 }
2488 } else if (!strcmp(args[1], "scope")) {
2489 if (*(args[2]) == 0) {
2490 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2494 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_ABORT;
2496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 }
2498 } else if (!strcmp(args[1], "enable")) {
2499 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2500 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002501 err_code |= ERR_ALERT | ERR_ABORT;
2502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002504 } else if (!strcmp(args[1], "hide-version")) {
2505 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2506 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_ABORT;
2508 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002509 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002510 } else if (!strcmp(args[1], "show-legends")) {
2511 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2512 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2513 err_code |= ERR_ALERT | ERR_ABORT;
2514 goto out;
2515 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002516 } else if (!strcmp(args[1], "show-node")) {
2517
2518 if (*args[2]) {
2519 int i;
2520 char c;
2521
2522 for (i=0; args[2][i]; i++) {
2523 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002524 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2525 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002526 break;
2527 }
2528
2529 if (!i || args[2][i]) {
2530 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2531 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2532 file, linenum, args[0], args[1]);
2533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
2535 }
2536 }
2537
2538 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2539 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2540 err_code |= ERR_ALERT | ERR_ABORT;
2541 goto out;
2542 }
2543 } else if (!strcmp(args[1], "show-desc")) {
2544 char *desc = NULL;
2545
2546 if (*args[2]) {
2547 int i, len=0;
2548 char *d;
2549
2550 for(i=2; *args[i]; i++)
2551 len += strlen(args[i])+1;
2552
2553 desc = d = (char *)calloc(1, len);
2554
2555 d += sprintf(d, "%s", args[2]);
2556 for(i=3; *args[i]; i++)
2557 d += sprintf(d, " %s", args[i]);
2558 }
2559
2560 if (!*args[2] && !global.desc)
2561 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2562 file, linenum, args[1]);
2563 else {
2564 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2565 free(desc);
2566 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2567 err_code |= ERR_ALERT | ERR_ABORT;
2568 goto out;
2569 }
2570 free(desc);
2571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002573stats_error_parsing:
2574 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2575 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
2579 }
2580 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002581 int optnum;
2582
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002583 if (*(args[1]) == '\0') {
2584 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2585 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002589
2590 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2591 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002592 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2593 err_code |= ERR_WARN;
2594 goto out;
2595 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002596
Willy Tarreau3842f002009-06-14 11:39:52 +02002597 curproxy->no_options &= ~cfg_opts[optnum].val;
2598 curproxy->options &= ~cfg_opts[optnum].val;
2599
2600 switch (kwm) {
2601 case KWM_STD:
2602 curproxy->options |= cfg_opts[optnum].val;
2603 break;
2604 case KWM_NO:
2605 curproxy->no_options |= cfg_opts[optnum].val;
2606 break;
2607 case KWM_DEF: /* already cleared */
2608 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002609 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002610
Willy Tarreau93893792009-07-23 13:19:11 +02002611 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002612 }
2613 }
2614
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002615 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2616 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002617 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2618 err_code |= ERR_WARN;
2619 goto out;
2620 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002621
Willy Tarreau3842f002009-06-14 11:39:52 +02002622 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2623 curproxy->options2 &= ~cfg_opts2[optnum].val;
2624
2625 switch (kwm) {
2626 case KWM_STD:
2627 curproxy->options2 |= cfg_opts2[optnum].val;
2628 break;
2629 case KWM_NO:
2630 curproxy->no_options2 |= cfg_opts2[optnum].val;
2631 break;
2632 case KWM_DEF: /* already cleared */
2633 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002634 }
Willy Tarreau93893792009-07-23 13:19:11 +02002635 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002636 }
2637 }
2638
Willy Tarreau3842f002009-06-14 11:39:52 +02002639 if (kwm != KWM_STD) {
2640 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002641 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002644 }
2645
Emeric Brun3a058f32009-06-30 18:26:00 +02002646 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002648 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002650 if (*(args[2]) != '\0') {
2651 if (!strcmp(args[2], "clf")) {
2652 curproxy->options2 |= PR_O2_CLFLOG;
2653 } else {
2654 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002657 }
2658 }
2659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 else if (!strcmp(args[1], "tcplog"))
2661 /* generate a detailed TCP log */
2662 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 else if (!strcmp(args[1], "tcpka")) {
2664 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002665 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002667
2668 if (curproxy->cap & PR_CAP_FE)
2669 curproxy->options |= PR_O_TCP_CLI_KA;
2670 if (curproxy->cap & PR_CAP_BE)
2671 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 }
2673 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002674 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_WARN;
2676
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002678 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002679 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002680 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002681 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002682 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002683 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 if (!*args[2]) { /* no argument */
2685 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2686 curproxy->check_len = strlen(DEF_CHECK_REQ);
2687 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002688 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 curproxy->check_req = (char *)malloc(reqlen);
2690 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002691 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002693 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 if (*args[4])
2695 reqlen += strlen(args[4]);
2696 else
2697 reqlen += strlen("HTTP/1.0");
2698
2699 curproxy->check_req = (char *)malloc(reqlen);
2700 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002701 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002703 }
2704 else if (!strcmp(args[1], "ssl-hello-chk")) {
2705 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002708
Willy Tarreaua534fea2008-08-03 12:19:50 +02002709 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002710 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002711 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002712 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002713 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002714 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 }
Willy Tarreau23677902007-05-08 23:50:35 +02002716 else if (!strcmp(args[1], "smtpchk")) {
2717 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002718 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002719 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002720 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002721 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002722 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002723 curproxy->options |= PR_O_SMTP_CHK;
2724
2725 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2726 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2727 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2728 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2729 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2730 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2731 curproxy->check_req = (char *)malloc(reqlen);
2732 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2733 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2734 } else {
2735 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2736 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2737 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2738 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2739 }
2740 }
2741 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002742 else if (!strcmp(args[1], "mysql-check")) {
2743 /* use MYSQL request to check servers' health */
2744 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002745 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002746 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002747 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002748 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002749 curproxy->options2 |= PR_O2_MYSQL_CHK;
2750 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002751 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002752 int cur_arg;
2753
2754 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2755 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002756 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002757
2758 curproxy->options |= PR_O_FWDFOR;
2759
2760 free(curproxy->fwdfor_hdr_name);
2761 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2762 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2763
2764 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2765 cur_arg = 2;
2766 while (*(args[cur_arg])) {
2767 if (!strcmp(args[cur_arg], "except")) {
2768 /* suboption except - needs additional argument for it */
2769 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2770 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2771 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002774 }
2775 /* flush useless bits */
2776 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002777 cur_arg += 2;
2778 } else if (!strcmp(args[cur_arg], "header")) {
2779 /* suboption header - needs additional argument for it */
2780 if (*(args[cur_arg+1]) == 0) {
2781 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2782 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002785 }
2786 free(curproxy->fwdfor_hdr_name);
2787 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2788 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2789 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002790 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002791 /* unknown suboption - catchall */
2792 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2793 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002796 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002797 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002798 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002799 else if (!strcmp(args[1], "originalto")) {
2800 int cur_arg;
2801
2802 /* insert x-original-to field, but not for the IP address listed as an except.
2803 * set default options (ie: bitfield, header name, etc)
2804 */
2805
2806 curproxy->options |= PR_O_ORGTO;
2807
2808 free(curproxy->orgto_hdr_name);
2809 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2810 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2811
2812 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2813 cur_arg = 2;
2814 while (*(args[cur_arg])) {
2815 if (!strcmp(args[cur_arg], "except")) {
2816 /* suboption except - needs additional argument for it */
2817 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2818 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2819 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002822 }
2823 /* flush useless bits */
2824 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2825 cur_arg += 2;
2826 } else if (!strcmp(args[cur_arg], "header")) {
2827 /* suboption header - needs additional argument for it */
2828 if (*(args[cur_arg+1]) == 0) {
2829 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2830 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002833 }
2834 free(curproxy->orgto_hdr_name);
2835 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2836 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2837 cur_arg += 2;
2838 } else {
2839 /* unknown suboption - catchall */
2840 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2841 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002844 }
2845 } /* end while loop */
2846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 else {
2848 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Willy Tarreau93893792009-07-23 13:19:11 +02002852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002854 else if (!strcmp(args[0], "default_backend")) {
2855 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002856 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002857
2858 if (*(args[1]) == 0) {
2859 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002862 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002863 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002864 curproxy->defbe.name = strdup(args[1]);
2865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002867 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002869
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002870 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2871 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 /* enable reconnections to dispatch */
2874 curproxy->options |= PR_O_REDISP;
2875 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002876 else if (!strcmp(args[0], "http-check")) {
2877 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002879
2880 if (strcmp(args[1], "disable-on-404") == 0) {
2881 /* enable a graceful server shutdown on an HTTP 404 response */
2882 curproxy->options |= PR_O_DISABLE404;
2883 }
Willy Tarreauef781042010-01-27 11:53:01 +01002884 else if (strcmp(args[1], "send-state") == 0) {
2885 /* enable emission of the apparent state of a server in HTTP checks */
2886 curproxy->options2 |= PR_O2_CHK_SNDST;
2887 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002888 else {
2889 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002892 }
2893 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002894 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002895 if (curproxy == &defproxy) {
2896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002899 }
2900
Willy Tarreaub80c2302007-11-30 20:51:32 +01002901 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002903
2904 if (strcmp(args[1], "fail") == 0) {
2905 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002906 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002907 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2908 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002911 }
2912
Willy Tarreauef6494c2010-01-28 17:12:36 +01002913 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002914 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2915 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002918 }
2919 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2920 }
2921 else {
2922 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002925 }
2926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927#ifdef TPROXY
2928 else if (!strcmp(args[0], "transparent")) {
2929 /* enable transparent proxy connections */
2930 curproxy->options |= PR_O_TRANSP;
2931 }
2932#endif
2933 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002936
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 if (*(args[1]) == 0) {
2938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 }
2942 curproxy->maxconn = atol(args[1]);
2943 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002944 else if (!strcmp(args[0], "backlog")) { /* backlog */
2945 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002947
2948 if (*(args[1]) == 0) {
2949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002952 }
2953 curproxy->backlog = atol(args[1]);
2954 }
Willy Tarreau86034312006-12-29 00:10:33 +01002955 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002956 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002957 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002958
Willy Tarreau86034312006-12-29 00:10:33 +01002959 if (*(args[1]) == 0) {
2960 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002963 }
2964 curproxy->fullconn = atol(args[1]);
2965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2967 if (*(args[1]) == 0) {
2968 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002972 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2973 if (err) {
2974 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2975 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002978 }
2979 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 }
2981 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01002982 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002983 if (curproxy == &defproxy) {
2984 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002988 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 if (strchr(args[1], ':') == NULL) {
2992 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01002996 sk = str2sa(args[1]);
2997 if (!sk) {
2998 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
2999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 }
3004 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003007
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003008 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003009 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3010 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003013 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003015 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3016 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3017 err_code |= ERR_WARN;
3018
3019 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3020 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3021 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3022 }
3023 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3024 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3025 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3026 }
3027 else {
3028 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
3032 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003033 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003035 char *rport, *raddr;
3036 short realport = 0;
3037 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003039 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003044 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046
3047 if (!*args[2]) {
3048 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003053
3054 err = invalid_char(args[1]);
3055 if (err) {
3056 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3057 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003060 }
3061
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003062 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003063 struct sockaddr_in *sk;
3064
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003065 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3066 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3067 err_code |= ERR_ALERT | ERR_ABORT;
3068 goto out;
3069 }
3070
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003071 /* the servers are linked backwards first */
3072 newsrv->next = curproxy->srv;
3073 curproxy->srv = newsrv;
3074 newsrv->proxy = curproxy;
3075 newsrv->conf.file = file;
3076 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003078 LIST_INIT(&newsrv->pendconns);
3079 do_check = 0;
3080 newsrv->state = SRV_RUNNING; /* early server setup */
3081 newsrv->last_change = now.tv_sec;
3082 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003084 /* several ways to check the port component :
3085 * - IP => port=+0, relative
3086 * - IP: => port=+0, relative
3087 * - IP:N => port=N, absolute
3088 * - IP:+N => port=+N, relative
3089 * - IP:-N => port=-N, relative
3090 */
3091 raddr = strdup(args[2]);
3092 rport = strchr(raddr, ':');
3093 if (rport) {
3094 *rport++ = 0;
3095 realport = atol(rport);
3096 if (!isdigit((unsigned char)*rport))
3097 newsrv->state |= SRV_MAPPORTS;
3098 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003100
Willy Tarreaud5191e72010-02-09 20:50:45 +01003101 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003102 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003103 if (!sk) {
3104 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108 newsrv->addr = *sk;
3109 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003110
3111 newsrv->check_port = curproxy->defsrv.check_port;
3112 newsrv->inter = curproxy->defsrv.inter;
3113 newsrv->fastinter = curproxy->defsrv.fastinter;
3114 newsrv->downinter = curproxy->defsrv.downinter;
3115 newsrv->rise = curproxy->defsrv.rise;
3116 newsrv->fall = curproxy->defsrv.fall;
3117 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3118 newsrv->minconn = curproxy->defsrv.minconn;
3119 newsrv->maxconn = curproxy->defsrv.maxconn;
3120 newsrv->slowstart = curproxy->defsrv.slowstart;
3121 newsrv->onerror = curproxy->defsrv.onerror;
3122 newsrv->consecutive_errors_limit
3123 = curproxy->defsrv.consecutive_errors_limit;
3124 newsrv->uweight = newsrv->iweight
3125 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003127 newsrv->curfd = -1; /* no health-check in progress */
3128 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003130 cur_arg = 3;
3131 } else {
3132 newsrv = &curproxy->defsrv;
3133 cur_arg = 1;
3134 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003135
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003137 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003138 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003139
3140 if (!*args[cur_arg + 1]) {
3141 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3142 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003145 }
3146
3147 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003148 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003149
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003150 if (newsrv->puid <= 0) {
3151 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003152 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003155 }
3156
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003157 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3158 if (node) {
3159 struct server *target = container_of(node, struct server, conf.id);
3160 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3161 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003166 cur_arg += 2;
3167 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003168 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 newsrv->cookie = strdup(args[cur_arg + 1]);
3170 newsrv->cklen = strlen(args[cur_arg + 1]);
3171 cur_arg += 2;
3172 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003173 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003174 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3175 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3176 cur_arg += 2;
3177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003179 if (!*args[cur_arg + 1]) {
3180 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3181 file, linenum, args[cur_arg]);
3182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
3184 }
3185
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003187 if (newsrv->rise <= 0) {
3188 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3189 file, linenum, args[cur_arg]);
3190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
3192 }
3193
Willy Tarreau96839092010-03-29 10:02:24 +02003194 if (newsrv->health)
3195 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 cur_arg += 2;
3197 }
3198 else if (!strcmp(args[cur_arg], "fall")) {
3199 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003200
3201 if (!*args[cur_arg + 1]) {
3202 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3203 file, linenum, args[cur_arg]);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
3207
3208 if (newsrv->fall <= 0) {
3209 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3210 file, linenum, args[cur_arg]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 cur_arg += 2;
3216 }
3217 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003218 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3219 if (err) {
3220 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3221 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003224 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003225 if (val <= 0) {
3226 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3227 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003230 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003231 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 cur_arg += 2;
3233 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003234 else if (!strcmp(args[cur_arg], "fastinter")) {
3235 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3236 if (err) {
3237 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3238 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003241 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003242 if (val <= 0) {
3243 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3244 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003247 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003248 newsrv->fastinter = val;
3249 cur_arg += 2;
3250 }
3251 else if (!strcmp(args[cur_arg], "downinter")) {
3252 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3253 if (err) {
3254 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3255 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003258 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003259 if (val <= 0) {
3260 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3261 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003264 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003265 newsrv->downinter = val;
3266 cur_arg += 2;
3267 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003268 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003269 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3270 if (!sk) {
3271 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
3274 }
3275 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003276 cur_arg += 2;
3277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 else if (!strcmp(args[cur_arg], "port")) {
3279 newsrv->check_port = atol(args[cur_arg + 1]);
3280 cur_arg += 2;
3281 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003282 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 newsrv->state |= SRV_BACKUP;
3284 cur_arg ++;
3285 }
3286 else if (!strcmp(args[cur_arg], "weight")) {
3287 int w;
3288 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003289 if (w < 0 || w > 256) {
3290 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003292 err_code |= ERR_ALERT | ERR_FATAL;
3293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003295 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 cur_arg += 2;
3297 }
3298 else if (!strcmp(args[cur_arg], "minconn")) {
3299 newsrv->minconn = atol(args[cur_arg + 1]);
3300 cur_arg += 2;
3301 }
3302 else if (!strcmp(args[cur_arg], "maxconn")) {
3303 newsrv->maxconn = atol(args[cur_arg + 1]);
3304 cur_arg += 2;
3305 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003306 else if (!strcmp(args[cur_arg], "maxqueue")) {
3307 newsrv->maxqueue = atol(args[cur_arg + 1]);
3308 cur_arg += 2;
3309 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003310 else if (!strcmp(args[cur_arg], "slowstart")) {
3311 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003312 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003313 if (err) {
3314 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3315 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003318 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003319 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003320 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3321 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003324 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003325 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003326 cur_arg += 2;
3327 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003328 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003329
3330 if (!*args[cur_arg + 1]) {
3331 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3332 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003335 }
3336
3337 newsrv->trackit = strdup(args[cur_arg + 1]);
3338
3339 cur_arg += 2;
3340 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003341 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 global.maxsock++;
3343 do_check = 1;
3344 cur_arg += 1;
3345 }
Willy Tarreau96839092010-03-29 10:02:24 +02003346 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3347 newsrv->state |= SRV_MAINTAIN;
3348 newsrv->state &= ~SRV_RUNNING;
3349 newsrv->health = 0;
3350 cur_arg += 1;
3351 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003352 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003353 if (!strcmp(args[cur_arg + 1], "none"))
3354 newsrv->observe = HANA_OBS_NONE;
3355 else if (!strcmp(args[cur_arg + 1], "layer4"))
3356 newsrv->observe = HANA_OBS_LAYER4;
3357 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3358 if (curproxy->mode != PR_MODE_HTTP) {
3359 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3360 file, linenum, args[cur_arg + 1]);
3361 err_code |= ERR_ALERT;
3362 }
3363 newsrv->observe = HANA_OBS_LAYER7;
3364 }
3365 else {
3366 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3367 "'l4events', 'http-responses' but get '%s'\n",
3368 file, linenum, args[cur_arg], args[cur_arg + 1]);
3369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
3371 }
3372
3373 cur_arg += 2;
3374 }
3375 else if (!strcmp(args[cur_arg], "on-error")) {
3376 if (!strcmp(args[cur_arg + 1], "fastinter"))
3377 newsrv->onerror = HANA_ONERR_FASTINTER;
3378 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3379 newsrv->onerror = HANA_ONERR_FAILCHK;
3380 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3381 newsrv->onerror = HANA_ONERR_SUDDTH;
3382 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3383 newsrv->onerror = HANA_ONERR_MARKDWN;
3384 else {
3385 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3386 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3387 file, linenum, args[cur_arg], args[cur_arg + 1]);
3388 err_code |= ERR_ALERT | ERR_FATAL;
3389 goto out;
3390 }
3391
3392 cur_arg += 2;
3393 }
3394 else if (!strcmp(args[cur_arg], "error-limit")) {
3395 if (!*args[cur_arg + 1]) {
3396 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3397 file, linenum, args[cur_arg]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
3402 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3403
3404 if (newsrv->consecutive_errors_limit <= 0) {
3405 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3406 file, linenum, args[cur_arg]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003410 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003411 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003412 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003413 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003414 struct sockaddr_in *sk;
3415
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003417#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003418 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003419 file, linenum, "source", "usesrc");
3420#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003421 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003423#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 }
3427 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003428 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3429 if (!sk) {
3430 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
3433 }
3434 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003435
3436 if (port_low != port_high) {
3437 int i;
3438 if (port_low <= 0 || port_low > 65535 ||
3439 port_high <= 0 || port_high > 65535 ||
3440 port_low > port_high) {
3441 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3442 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003445 }
3446 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3447 for (i = 0; i < newsrv->sport_range->size; i++)
3448 newsrv->sport_range->ports[i] = port_low + i;
3449 }
3450
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003452 while (*(args[cur_arg])) {
3453 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003454#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3455#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003456 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3457 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3458 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003461 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003462#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003463 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003464 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01003465 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003468 }
3469 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003470 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003471 newsrv->state |= SRV_TPROXY_CLI;
3472 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003473 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003474 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003475 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3476 char *name, *end;
3477
3478 name = args[cur_arg+1] + 7;
3479 while (isspace(*name))
3480 name++;
3481
3482 end = name;
3483 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3484 end++;
3485
3486 newsrv->state &= ~SRV_TPROXY_MASK;
3487 newsrv->state |= SRV_TPROXY_DYN;
3488 newsrv->bind_hdr_name = calloc(1, end - name + 1);
3489 newsrv->bind_hdr_len = end - name;
3490 memcpy(newsrv->bind_hdr_name, name, end - name);
3491 newsrv->bind_hdr_name[end-name] = '\0';
3492 newsrv->bind_hdr_occ = -1;
3493
3494 /* now look for an occurrence number */
3495 while (isspace(*end))
3496 end++;
3497 if (*end == ',') {
3498 end++;
3499 name = end;
3500 if (*end == '-')
3501 end++;
3502 while (isdigit(*end))
3503 end++;
3504 newsrv->bind_hdr_occ = strl2ic(name, end-name);
3505 }
3506
3507 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
3508 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3509 " occurrences values smaller than %d.\n",
3510 file, linenum, MAX_HDR_HISTORY);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01003514 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003515 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3516 if (!sk) {
3517 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
3521 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003522 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003523 }
3524 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003525#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003526 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003527#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003528 cur_arg += 2;
3529 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003530#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003531 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003532 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003535#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3536 } /* "usesrc" */
3537
3538 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3539#ifdef SO_BINDTODEVICE
3540 if (!*args[cur_arg + 1]) {
3541 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003545 }
3546 if (newsrv->iface_name)
3547 free(newsrv->iface_name);
3548
3549 newsrv->iface_name = strdup(args[cur_arg + 1]);
3550 newsrv->iface_len = strlen(newsrv->iface_name);
3551 global.last_checks |= LSTCHK_NETADM;
3552#else
3553 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3554 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003557#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003558 cur_arg += 2;
3559 continue;
3560 }
3561 /* this keyword in not an option of "source" */
3562 break;
3563 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003565 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003566 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3567 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003572 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003573 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003574 file, linenum, newsrv->id);
3575 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003576 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003577 file, linenum);
3578
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 }
3582 }
3583
3584 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003585 if (newsrv->trackit) {
3586 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3587 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003590 }
3591
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003592 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3593 newsrv->check_port = newsrv->check_addr.sin_port;
3594
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3596 newsrv->check_port = realport; /* by default */
3597 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003598 /* not yet valid, because no port was set on
3599 * the server either. We'll check if we have
3600 * a known port on the first listener.
3601 */
3602 struct listener *l;
3603 l = curproxy->listen;
3604 if (l) {
3605 int port;
3606 port = (l->addr.ss_family == AF_INET6)
3607 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3608 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3609 newsrv->check_port = port;
3610 }
3611 }
3612 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3614 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003618
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003619 /* Allocate buffer for partial check results... */
3620 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3621 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3622 err_code |= ERR_ALERT | ERR_ABORT;
3623 goto out;
3624 }
3625
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003626 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 newsrv->state |= SRV_CHECKED;
3628 }
3629
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003630 if (!defsrv) {
3631 if (newsrv->state & SRV_BACKUP)
3632 curproxy->srv_bck++;
3633 else
3634 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003635
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003636 newsrv->prev_state = newsrv->state;
3637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
3639 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003640 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 int facility;
3642
3643 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3644 curproxy->logfac1 = global.logfac1;
3645 curproxy->logsrv1 = global.logsrv1;
3646 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003647 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003648 curproxy->logfac2 = global.logfac2;
3649 curproxy->logsrv2 = global.logsrv2;
3650 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003651 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
3653 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003654 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655
3656 facility = get_log_facility(args[2]);
3657 if (facility < 0) {
3658 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3659 exit(1);
3660 }
3661
3662 level = 7; /* max syslog level = debug */
3663 if (*(args[3])) {
3664 level = get_log_level(args[3]);
3665 if (level < 0) {
3666 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3667 exit(1);
3668 }
3669 }
3670
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003671 minlvl = 0; /* limit syslog level to this level (emerg) */
3672 if (*(args[4])) {
3673 minlvl = get_log_level(args[4]);
3674 if (level < 0) {
3675 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3676 exit(1);
3677 }
3678 }
3679
Robert Tsai81ae1952007-12-05 10:47:29 +01003680 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003681 struct sockaddr_un *sk = str2sun(args[1]);
3682 if (!sk) {
3683 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3684 args[1], (int)sizeof(sk->sun_path) - 1);
3685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
3687 }
3688 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003689 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003690 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003691 struct sockaddr_in *sk = str2sa(args[1]);
3692 if (!sk) {
3693 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
3697 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003698 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003699 if (!logsrv.u.in.sin_port) {
3700 logsrv.u.in.sin_port =
3701 htons(SYSLOG_PORT);
3702 }
3703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704
3705 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003706 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 curproxy->logfac1 = facility;
3708 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003709 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 }
3711 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003712 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003713 curproxy->logfac2 = facility;
3714 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003715 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
3717 else {
3718 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
3722 }
3723 else {
3724 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3725 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
3729 }
3730 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003731 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003732 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003733
Willy Tarreau977b8e42006-12-29 14:19:17 +01003734 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003735 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003736
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003738 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3739 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003743
3744 /* we must first clear any optional default setting */
3745 curproxy->options &= ~PR_O_TPXY_MASK;
3746 free(curproxy->iface_name);
3747 curproxy->iface_name = NULL;
3748 curproxy->iface_len = 0;
3749
Willy Tarreaud5191e72010-02-09 20:50:45 +01003750 sk = str2sa(args[1]);
3751 if (!sk) {
3752 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
3756 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003758
3759 cur_arg = 2;
3760 while (*(args[cur_arg])) {
3761 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003762#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3763#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003764 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3765 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3766 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003769 }
3770#endif
3771 if (!*args[cur_arg + 1]) {
3772 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3773 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003776 }
3777
3778 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003779 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003780 curproxy->options |= PR_O_TPXY_CLI;
3781 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003782 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003783 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003784 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3785 char *name, *end;
3786
3787 name = args[cur_arg+1] + 7;
3788 while (isspace(*name))
3789 name++;
3790
3791 end = name;
3792 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3793 end++;
3794
3795 curproxy->options &= ~PR_O_TPXY_MASK;
3796 curproxy->options |= PR_O_TPXY_DYN;
3797 curproxy->bind_hdr_name = calloc(1, end - name + 1);
3798 curproxy->bind_hdr_len = end - name;
3799 memcpy(curproxy->bind_hdr_name, name, end - name);
3800 curproxy->bind_hdr_name[end-name] = '\0';
3801 curproxy->bind_hdr_occ = -1;
3802
3803 /* now look for an occurrence number */
3804 while (isspace(*end))
3805 end++;
3806 if (*end == ',') {
3807 end++;
3808 name = end;
3809 if (*end == '-')
3810 end++;
3811 while (isdigit(*end))
3812 end++;
3813 curproxy->bind_hdr_occ = strl2ic(name, end-name);
3814 }
3815
3816 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
3817 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3818 " occurrences values smaller than %d.\n",
3819 file, linenum, MAX_HDR_HISTORY);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003823 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003824 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3825 if (!sk) {
3826 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003831 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003832 }
3833 global.last_checks |= LSTCHK_NETADM;
3834#if !defined(CONFIG_HAP_LINUX_TPROXY)
3835 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003836#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003837#else /* no TPROXY support */
3838 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003839 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003842#endif
3843 cur_arg += 2;
3844 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003845 }
3846
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003847 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3848#ifdef SO_BINDTODEVICE
3849 if (!*args[cur_arg + 1]) {
3850 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3851 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003854 }
3855 if (curproxy->iface_name)
3856 free(curproxy->iface_name);
3857
3858 curproxy->iface_name = strdup(args[cur_arg + 1]);
3859 curproxy->iface_len = strlen(curproxy->iface_name);
3860 global.last_checks |= LSTCHK_NETADM;
3861#else
3862 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3863 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003866#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003867 cur_arg += 2;
3868 continue;
3869 }
3870 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3871 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003874 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003876 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3877 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3878 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003883 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3885 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003889
3890 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3891 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003892 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003893 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895 }
3896 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003897 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3898 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003899 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003900 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 }
3903 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003904 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3905 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003906 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003907 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 }
3910 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003911 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3912 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003913 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003914 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916 }
3917 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3919 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003920 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003924 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3926 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003927 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003929 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003930 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003931 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3933 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003934 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003936 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003937 }
3938 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3940 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003941 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003943 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003946 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003952
3953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3954 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003955 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958 }
3959 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3961 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003962 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965 }
3966 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3968 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 }
3973 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3975 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003976 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 }
3980 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003981 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3982 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003983 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003984 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003987 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3989 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003990 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003992 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003995 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003996
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 if (curproxy == &defproxy) {
3998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004002 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 if (*(args[1]) == 0) {
4006 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004010
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004011 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4012 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4013 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4014 file, linenum, args[0]);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4019 }
4020 else if (*args[2]) {
4021 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4022 file, linenum, args[0], args[2]);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025 }
4026
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004027 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004028 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004029 wl->s = strdup(args[1]);
4030 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004031 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 }
4033 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004034 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4036 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004040
Willy Tarreauade5ec42010-01-28 19:33:49 +01004041 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4042 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004043 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004044 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 }
4047 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004048 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4049 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004050 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004051 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 }
4054 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004055 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4056 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004057 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004058 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 }
4061 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004062 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 }
4068
Willy Tarreauade5ec42010-01-28 19:33:49 +01004069 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4070 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004071 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004072 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004074 }
4075 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004076 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4077 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004078 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004079 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 }
4082 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004083 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4084 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004085 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004086 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004088 }
4089 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004090 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004091
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 if (curproxy == &defproxy) {
4093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004096 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004097 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 if (*(args[1]) == 0) {
4101 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 }
4105
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004106 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4107 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4108 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4109 file, linenum, args[0]);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
4113 err_code |= warnif_cond_requires_req(cond, file, linenum);
4114 }
4115 else if (*args[2]) {
4116 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4117 file, linenum, args[0], args[2]);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004122 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004123 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004124 wl->s = strdup(args[1]);
4125 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 }
4127 else if (!strcmp(args[0], "errorloc") ||
4128 !strcmp(args[0], "errorloc302") ||
4129 !strcmp(args[0], "errorloc303")) { /* error location */
4130 int errnum, errlen;
4131 char *err;
4132
Willy Tarreau977b8e42006-12-29 14:19:17 +01004133 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004135
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004137 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 }
4141
4142 errnum = atol(args[1]);
4143 if (!strcmp(args[0], "errorloc303")) {
4144 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4145 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4146 } else {
4147 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4148 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4149 }
4150
Willy Tarreau0f772532006-12-23 20:51:41 +01004151 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4152 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004153 chunk_destroy(&curproxy->errmsg[rc]);
4154 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004155 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004157 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004158
4159 if (rc >= HTTP_ERR_SIZE) {
4160 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4161 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 free(err);
4163 }
4164 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004165 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4166 int errnum, errlen, fd;
4167 char *err;
4168 struct stat stat;
4169
4170 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004171 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004172
4173 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004174 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004177 }
4178
4179 fd = open(args[2], O_RDONLY);
4180 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4181 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4182 file, linenum, args[2], args[1]);
4183 if (fd >= 0)
4184 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004187 }
4188
Willy Tarreau27a674e2009-08-17 07:23:33 +02004189 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004190 errlen = stat.st_size;
4191 } else {
4192 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004193 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004195 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004196 }
4197
4198 err = malloc(errlen); /* malloc() must succeed during parsing */
4199 errnum = read(fd, err, errlen);
4200 if (errnum != errlen) {
4201 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4202 file, linenum, args[2], args[1]);
4203 close(fd);
4204 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004207 }
4208 close(fd);
4209
4210 errnum = atol(args[1]);
4211 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4212 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004213 chunk_destroy(&curproxy->errmsg[rc]);
4214 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004215 break;
4216 }
4217 }
4218
4219 if (rc >= HTTP_ERR_SIZE) {
4220 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4221 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004223 free(err);
4224 }
4225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004227 struct cfg_kw_list *kwl;
4228 int index;
4229
4230 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4231 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4232 if (kwl->kw[index].section != CFG_LISTEN)
4233 continue;
4234 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4235 /* prepare error message just in case */
4236 snprintf(trash, sizeof(trash),
4237 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004238 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4239 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004240 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004243 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004244 else if (rc > 0) {
4245 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_WARN;
4247 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004248 }
Willy Tarreau93893792009-07-23 13:19:11 +02004249 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004250 }
4251 }
4252 }
4253
Willy Tarreau6daf3432008-01-22 16:44:08 +01004254 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 }
Willy Tarreau93893792009-07-23 13:19:11 +02004258 out:
4259 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260}
4261
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004262int
4263cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4264{
4265
4266 int err_code = 0;
4267 const char *err;
4268
4269 if (!strcmp(args[0], "userlist")) { /* new userlist */
4270 struct userlist *newul;
4271
4272 if (!*args[1]) {
4273 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4274 file, linenum, args[0]);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
4278
4279 err = invalid_char(args[1]);
4280 if (err) {
4281 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4282 file, linenum, *err, args[0], args[1]);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 }
4286
4287 for (newul = userlist; newul; newul = newul->next)
4288 if (!strcmp(newul->name, args[1])) {
4289 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4290 file, linenum, args[1]);
4291 err_code |= ERR_WARN;
4292 goto out;
4293 }
4294
4295 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4296 if (!newul) {
4297 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4298 err_code |= ERR_ALERT | ERR_ABORT;
4299 goto out;
4300 }
4301
4302 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4303 newul->name = strdup(args[1]);
4304
4305 if (!newul->groupusers | !newul->name) {
4306 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4307 err_code |= ERR_ALERT | ERR_ABORT;
4308 goto out;
4309 }
4310
4311 newul->next = userlist;
4312 userlist = newul;
4313
4314 } else if (!strcmp(args[0], "group")) { /* new group */
4315 int cur_arg, i;
4316 const char *err;
4317
4318 if (!*args[1]) {
4319 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4320 file, linenum, args[0]);
4321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324
4325 err = invalid_char(args[1]);
4326 if (err) {
4327 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4328 file, linenum, *err, args[0], args[1]);
4329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332
4333 for(i = 0; i < userlist->grpcnt; i++)
4334 if (!strcmp(userlist->groups[i], args[1])) {
4335 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4336 file, linenum, args[1], userlist->name);
4337 err_code |= ERR_ALERT;
4338 goto out;
4339 }
4340
4341 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4342 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4343 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
4346 }
4347
4348 cur_arg = 2;
4349
4350 while (*args[cur_arg]) {
4351 if (!strcmp(args[cur_arg], "users")) {
4352 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4353 cur_arg += 2;
4354 continue;
4355 } else {
4356 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4357 file, linenum, args[0]);
4358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
4360 }
4361 }
4362
4363 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4364 } else if (!strcmp(args[0], "user")) { /* new user */
4365 struct auth_users *newuser;
4366 int cur_arg;
4367
4368 if (!*args[1]) {
4369 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4370 file, linenum, args[0]);
4371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
4373 }
4374
4375 for (newuser = userlist->users; newuser; newuser = newuser->next)
4376 if (!strcmp(newuser->user, args[1])) {
4377 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4378 file, linenum, args[1], userlist->name);
4379 err_code |= ERR_ALERT;
4380 goto out;
4381 }
4382
4383 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4384 if (!newuser) {
4385 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
4388 }
4389
4390 newuser->user = strdup(args[1]);
4391
4392 newuser->next = userlist->users;
4393 userlist->users = newuser;
4394
4395 cur_arg = 2;
4396
4397 while (*args[cur_arg]) {
4398 if (!strcmp(args[cur_arg], "password")) {
4399#ifndef CONFIG_HAP_CRYPT
4400 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4401 file, linenum);
4402 err_code |= ERR_ALERT;
4403#endif
4404 newuser->pass = strdup(args[cur_arg + 1]);
4405 cur_arg += 2;
4406 continue;
4407 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4408 newuser->pass = strdup(args[cur_arg + 1]);
4409 newuser->flags |= AU_O_INSECURE;
4410 cur_arg += 2;
4411 continue;
4412 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004413 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004414 cur_arg += 2;
4415 continue;
4416 } else {
4417 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4418 file, linenum, args[0]);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422 }
4423 } else {
4424 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 }
4427
4428out:
4429 return err_code;
4430}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431
4432/*
4433 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004434 * Returns the error code, 0 if OK, or any combination of :
4435 * - ERR_ABORT: must abort ASAP
4436 * - ERR_FATAL: we can continue parsing but not start the service
4437 * - ERR_WARN: a warning has been emitted
4438 * - ERR_ALERT: an alert has been emitted
4439 * Only the two first ones can stop processing, the two others are just
4440 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004442int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004444 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 FILE *f;
4446 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004448 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 if ((f=fopen(file,"r")) == NULL)
4451 return -1;
4452
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004453 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004454 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004455 char *end;
4456 char *args[MAX_LINE_ARGS + 1];
4457 char *line = thisline;
4458
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 linenum++;
4460
4461 end = line + strlen(line);
4462
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004463 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4464 /* Check if we reached the limit and the last char is not \n.
4465 * Watch out for the last line without the terminating '\n'!
4466 */
4467 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004468 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004470 }
4471
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004473 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 line++;
4475
4476 arg = 0;
4477 args[arg] = line;
4478
4479 while (*line && arg < MAX_LINE_ARGS) {
4480 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4481 * C equivalent value. Other combinations left unchanged (eg: \1).
4482 */
4483 if (*line == '\\') {
4484 int skip = 0;
4485 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4486 *line = line[1];
4487 skip = 1;
4488 }
4489 else if (line[1] == 'r') {
4490 *line = '\r';
4491 skip = 1;
4492 }
4493 else if (line[1] == 'n') {
4494 *line = '\n';
4495 skip = 1;
4496 }
4497 else if (line[1] == 't') {
4498 *line = '\t';
4499 skip = 1;
4500 }
4501 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004502 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 unsigned char hex1, hex2;
4504 hex1 = toupper(line[2]) - '0';
4505 hex2 = toupper(line[3]) - '0';
4506 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4507 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4508 *line = (hex1<<4) + hex2;
4509 skip = 3;
4510 }
4511 else {
4512 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004513 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 }
4515 }
4516 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004517 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 end -= skip;
4519 }
4520 line++;
4521 }
4522 else if (*line == '#' || *line == '\n' || *line == '\r') {
4523 /* end of string, end of loop */
4524 *line = 0;
4525 break;
4526 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004527 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004528 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004529 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004530 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 line++;
4532 args[++arg] = line;
4533 }
4534 else {
4535 line++;
4536 }
4537 }
4538
4539 /* empty line */
4540 if (!**args)
4541 continue;
4542
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004543 if (*line) {
4544 /* we had to stop due to too many args.
4545 * Let's terminate the string, print the offending part then cut the
4546 * last arg.
4547 */
4548 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4549 line++;
4550 *line = '\0';
4551
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004552 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004553 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004554 err_code |= ERR_ALERT | ERR_FATAL;
4555 args[arg] = line;
4556 }
4557
Willy Tarreau540abe42007-05-02 20:50:16 +02004558 /* zero out remaining args and ensure that at least one entry
4559 * is zeroed out.
4560 */
4561 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004562 args[arg] = line;
4563 }
4564
Willy Tarreau3842f002009-06-14 11:39:52 +02004565 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004566 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004567 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004568 for (arg=0; *args[arg+1]; arg++)
4569 args[arg] = args[arg+1]; // shift args after inversion
4570 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004571 else if (!strcmp(args[0], "default")) {
4572 kwm = KWM_DEF;
4573 for (arg=0; *args[arg+1]; arg++)
4574 args[arg] = args[arg+1]; // shift args after inversion
4575 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004576
Willy Tarreau3842f002009-06-14 11:39:52 +02004577 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4578 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004580 }
4581
Willy Tarreau977b8e42006-12-29 14:19:17 +01004582 if (!strcmp(args[0], "listen") ||
4583 !strcmp(args[0], "frontend") ||
4584 !strcmp(args[0], "backend") ||
4585 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004586 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004587 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004588 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004589 cursection = strdup(args[0]);
4590 }
4591 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004593 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004594 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004595 } else if (!strcmp(args[0], "userlist")) {
4596 confsect = CFG_USERLIST;
4597 free(cursection);
4598 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 /* else it's a section keyword */
4601
4602 switch (confsect) {
4603 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 break;
4606 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004607 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004609 case CFG_USERLIST:
4610 err_code |= cfg_parse_users(file, linenum, args, kwm);
4611 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004613 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004615 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004616
4617 if (err_code & ERR_ABORT)
4618 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004620 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004621 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004623 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004624}
4625
Willy Tarreaubb925012009-07-23 13:36:36 +02004626/*
4627 * Returns the error code, 0 if OK, or any combination of :
4628 * - ERR_ABORT: must abort ASAP
4629 * - ERR_FATAL: we can continue parsing but not start the service
4630 * - ERR_WARN: a warning has been emitted
4631 * - ERR_ALERT: an alert has been emitted
4632 * Only the two first ones can stop processing, the two others are just
4633 * indicators.
4634 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004635int check_config_validity()
4636{
4637 int cfgerr = 0;
4638 struct proxy *curproxy = NULL;
4639 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004640 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004641 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004642 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643
4644 /*
4645 * Now, check for the integrity of all that we have collected.
4646 */
4647
4648 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004649 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004651 /* first, we will invert the proxy list order */
4652 curproxy = NULL;
4653 while (proxy) {
4654 struct proxy *next;
4655
4656 next = proxy->next;
4657 proxy->next = curproxy;
4658 curproxy = proxy;
4659 if (!next)
4660 break;
4661 proxy = next;
4662 }
4663
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004665 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 }
4669
4670 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004671 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004672 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004673 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004674 unsigned int next_id;
4675
4676 if (!curproxy->uuid) {
4677 /* proxy ID not set, use automatic numbering with first
4678 * spare entry starting with next_pxid.
4679 */
4680 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4681 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4682 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004683 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004684 next_pxid++;
4685
Willy Tarreau55ea7572007-06-17 19:56:27 +02004686
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004688 /* ensure we don't keep listeners uselessly bound */
4689 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 curproxy = curproxy->next;
4691 continue;
4692 }
4693
Willy Tarreauff01a212009-03-15 13:46:16 +01004694 switch (curproxy->mode) {
4695 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004696 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004697 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004698 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4699 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004700 cfgerr++;
4701 }
4702
4703 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004704 Warning("config : servers will be ignored for %s '%s'.\n",
4705 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004706 break;
4707
4708 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004709 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004710 break;
4711
4712 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004713 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004714 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004715 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4716 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004717 cfgerr++;
4718 }
4719 break;
4720 }
4721
4722 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004723 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4724 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004725 cfgerr++;
4726 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004727
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004728 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004729 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004730 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004731 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4732 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004733 cfgerr++;
4734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004736 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004737 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4738 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004739 cfgerr++;
4740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004742 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004743 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4744 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004745 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004746 }
4747 }
4748 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4749 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4750 /* If no LB algo is set in a backend, and we're not in
4751 * transparent mode, dispatch mode nor proxy mode, we
4752 * want to use balance roundrobin by default.
4753 */
4754 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4755 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
4757 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004758
Willy Tarreau82936582007-11-30 15:20:09 +01004759 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4760 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004761 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4762 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004763 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004764 }
4765
Willy Tarreauef781042010-01-27 11:53:01 +01004766 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4767 curproxy->options &= ~PR_O2_CHK_SNDST;
4768 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4769 "send-state", proxy_type_str(curproxy), curproxy->id);
4770 err_code |= ERR_WARN;
4771 }
4772
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004773 /* if a default backend was specified, let's find it */
4774 if (curproxy->defbe.name) {
4775 struct proxy *target;
4776
Alex Williams96532db2009-11-01 21:27:13 -05004777 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004778 if (!target) {
4779 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4780 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004781 cfgerr++;
4782 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004783 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4784 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004785 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004786 } else {
4787 free(curproxy->defbe.name);
4788 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004789 /* we force the backend to be present on at least all of
4790 * the frontend's processes.
4791 */
4792 target->bind_proc = curproxy->bind_proc ?
4793 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 }
4795 }
4796
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004797 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004798 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4799 /* map jump target for ACT_SETBE in req_rep chain */
4800 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004801 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004802 struct proxy *target;
4803
Willy Tarreaua496b602006-12-17 23:15:24 +01004804 if (exp->action != ACT_SETBE)
4805 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004806
Alex Williams96532db2009-11-01 21:27:13 -05004807 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004808 if (!target) {
4809 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4810 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004811 cfgerr++;
4812 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004813 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4814 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004815 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004816 } else {
4817 free((void *)exp->replace);
4818 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004819 /* we force the backend to be present on at least all of
4820 * the frontend's processes.
4821 */
4822 target->bind_proc = curproxy->bind_proc ?
4823 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004824 }
4825 }
4826 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004827
4828 /* find the target proxy for 'use_backend' rules */
4829 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004830 struct proxy *target;
4831
Alex Williams96532db2009-11-01 21:27:13 -05004832 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004833
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004834 if (!target) {
4835 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4836 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004837 cfgerr++;
4838 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004839 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4840 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004841 cfgerr++;
4842 } else {
4843 free((void *)rule->be.name);
4844 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004845 /* we force the backend to be present on at least all of
4846 * the frontend's processes.
4847 */
4848 target->bind_proc = curproxy->bind_proc ?
4849 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004850 }
4851 }
4852
Emeric Brunb982a3d2010-01-04 15:45:53 +01004853 /* find the target table for 'stick' rules */
4854 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4855 struct proxy *target;
4856
Emeric Brun1d33b292010-01-04 15:47:17 +01004857 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4858 if (mrule->flags & STK_IS_STORE)
4859 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4860
Emeric Brunb982a3d2010-01-04 15:45:53 +01004861 if (mrule->table.name)
4862 target = findproxy(mrule->table.name, PR_CAP_BE);
4863 else
4864 target = curproxy;
4865
4866 if (!target) {
4867 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4868 curproxy->id, mrule->table.name);
4869 cfgerr++;
4870 }
4871 else if (target->table.size == 0) {
4872 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4873 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4874 cfgerr++;
4875 }
4876 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4877 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4878 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4879 cfgerr++;
4880 }
4881 else {
4882 free((void *)mrule->table.name);
4883 mrule->table.t = &(target->table);
4884 }
4885 }
4886
4887 /* find the target table for 'store response' rules */
4888 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4889 struct proxy *target;
4890
Emeric Brun1d33b292010-01-04 15:47:17 +01004891 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4892
Emeric Brunb982a3d2010-01-04 15:45:53 +01004893 if (mrule->table.name)
4894 target = findproxy(mrule->table.name, PR_CAP_BE);
4895 else
4896 target = curproxy;
4897
4898 if (!target) {
4899 Alert("Proxy '%s': unable to find store table '%s'.\n",
4900 curproxy->id, mrule->table.name);
4901 cfgerr++;
4902 }
4903 else if (target->table.size == 0) {
4904 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4905 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4906 cfgerr++;
4907 }
4908 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4909 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4910 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4911 cfgerr++;
4912 }
4913 else {
4914 free((void *)mrule->table.name);
4915 mrule->table.t = &(target->table);
4916 }
4917 }
4918
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004919 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4920 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004921 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4922 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4923 "proxy", curproxy->id);
4924 cfgerr++;
4925 goto out_uri_auth_compat;
4926 }
4927
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004928 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004929 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004930 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004931 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004932
Willy Tarreau95fa4692010-02-01 13:05:50 +01004933 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4934 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004935
4936 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004937 uri_auth_compat_req[i++] = "realm";
4938 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4939 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004940
Willy Tarreau95fa4692010-02-01 13:05:50 +01004941 uri_auth_compat_req[i++] = "unless";
4942 uri_auth_compat_req[i++] = "{";
4943 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4944 uri_auth_compat_req[i++] = "}";
4945 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004946
Willy Tarreau95fa4692010-02-01 13:05:50 +01004947 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4948 if (!req_acl) {
4949 cfgerr++;
4950 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004951 }
4952
Willy Tarreau95fa4692010-02-01 13:05:50 +01004953 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4954
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004955 if (curproxy->uri_auth->auth_realm) {
4956 free(curproxy->uri_auth->auth_realm);
4957 curproxy->uri_auth->auth_realm = NULL;
4958 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004959
4960 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004961 }
4962out_uri_auth_compat:
4963
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004964 cfgerr += acl_find_targets(curproxy);
4965
Willy Tarreau2738a142006-07-08 17:28:09 +02004966 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004967 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004968 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004969 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004970 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004971 " | While not properly invalid, you will certainly encounter various problems\n"
4972 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004973 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004974 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004975 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004976 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004977
Willy Tarreau1fa31262007-12-03 00:36:16 +01004978 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4979 * We must still support older configurations, so let's find out whether those
4980 * parameters have been set or must be copied from contimeouts.
4981 */
4982 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004983 if (!curproxy->timeout.tarpit ||
4984 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004985 /* tarpit timeout not set. We search in the following order:
4986 * default.tarpit, curr.connect, default.connect.
4987 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004988 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004989 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004990 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004991 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004992 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004993 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004994 }
4995 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004996 (!curproxy->timeout.queue ||
4997 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004998 /* queue timeout not set. We search in the following order:
4999 * default.queue, curr.connect, default.connect.
5000 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005001 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005002 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005003 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005004 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005005 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005006 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005007 }
5008 }
5009
Willy Tarreau07a54902010-03-29 18:33:29 +02005010 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005011 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5012 curproxy->check_req = (char *)malloc(curproxy->check_len);
5013 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005014 }
5015
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005016 /* The small pools required for the capture lists */
5017 if (curproxy->nb_req_cap)
5018 curproxy->req_cap_pool = create_pool("ptrcap",
5019 curproxy->nb_req_cap * sizeof(char *),
5020 MEM_F_SHARED);
5021 if (curproxy->nb_rsp_cap)
5022 curproxy->rsp_cap_pool = create_pool("ptrcap",
5023 curproxy->nb_rsp_cap * sizeof(char *),
5024 MEM_F_SHARED);
5025
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005026 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5027 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5028 MEM_F_SHARED);
5029
Willy Tarreau86034312006-12-29 00:10:33 +01005030 /* for backwards compatibility with "listen" instances, if
5031 * fullconn is not set but maxconn is set, then maxconn
5032 * is used.
5033 */
5034 if (!curproxy->fullconn)
5035 curproxy->fullconn = curproxy->maxconn;
5036
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 /* first, we will invert the servers list order */
5038 newsrv = NULL;
5039 while (curproxy->srv) {
5040 struct server *next;
5041
5042 next = curproxy->srv->next;
5043 curproxy->srv->next = newsrv;
5044 newsrv = curproxy->srv;
5045 if (!next)
5046 break;
5047 curproxy->srv = next;
5048 }
5049
Willy Tarreaudd701652010-05-25 23:03:02 +02005050 /* assign automatic UIDs to servers which don't have one yet */
5051 next_id = 1;
5052 newsrv = curproxy->srv;
5053 while (newsrv != NULL) {
5054 if (!newsrv->puid) {
5055 /* server ID not set, use automatic numbering with first
5056 * spare entry starting with next_svid.
5057 */
5058 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5059 newsrv->conf.id.key = newsrv->puid = next_id;
5060 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5061 }
5062 next_id++;
5063 newsrv = newsrv->next;
5064 }
5065
Willy Tarreau20697042007-11-15 23:26:18 +01005066 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005067 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005069 /* We have to initialize the server lookup mechanism depending
5070 * on what LB algorithm was choosen.
5071 */
5072
5073 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5074 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5075 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005076 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5077 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5078 init_server_map(curproxy);
5079 } else {
5080 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5081 fwrr_init_server_groups(curproxy);
5082 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005083 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005084
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005085 case BE_LB_KIND_LC:
5086 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005087 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005088 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005089
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005090 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005091 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5092 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5093 chash_init_server_tree(curproxy);
5094 } else {
5095 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5096 init_server_map(curproxy);
5097 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005098 break;
5099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100
5101 if (curproxy->options & PR_O_LOGASAP)
5102 curproxy->to_log &= ~LW_BYTES;
5103
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005104 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5105 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5106 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5107 proxy_type_str(curproxy), curproxy->id);
5108 err_code |= ERR_WARN;
5109 }
5110
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005111 if (curproxy->mode != PR_MODE_HTTP) {
5112 int optnum;
5113
5114 if (curproxy->options & PR_O_COOK_ANY) {
5115 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5116 proxy_type_str(curproxy), curproxy->id);
5117 err_code |= ERR_WARN;
5118 }
5119
5120 if (curproxy->uri_auth) {
5121 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5122 proxy_type_str(curproxy), curproxy->id);
5123 err_code |= ERR_WARN;
5124 curproxy->uri_auth = NULL;
5125 }
5126
5127 if (curproxy->options & PR_O_FWDFOR) {
5128 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5129 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5130 err_code |= ERR_WARN;
5131 curproxy->options &= ~PR_O_FWDFOR;
5132 }
5133
5134 if (curproxy->options & PR_O_ORGTO) {
5135 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5136 "originalto", proxy_type_str(curproxy), curproxy->id);
5137 err_code |= ERR_WARN;
5138 curproxy->options &= ~PR_O_ORGTO;
5139 }
5140
5141 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5142 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5143 (curproxy->cap & cfg_opts[optnum].cap) &&
5144 (curproxy->options & cfg_opts[optnum].val)) {
5145 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5146 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5147 err_code |= ERR_WARN;
5148 curproxy->options &= ~cfg_opts[optnum].val;
5149 }
5150 }
5151
5152 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5153 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5154 (curproxy->cap & cfg_opts2[optnum].cap) &&
5155 (curproxy->options2 & cfg_opts2[optnum].val)) {
5156 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5157 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5158 err_code |= ERR_WARN;
5159 curproxy->options2 &= ~cfg_opts2[optnum].val;
5160 }
5161 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005162
Willy Tarreauefa5f512010-03-30 20:13:29 +02005163#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005164 if (curproxy->bind_hdr_occ) {
5165 curproxy->bind_hdr_occ = 0;
5166 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5167 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5168 err_code |= ERR_WARN;
5169 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005170#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005171 }
5172
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005174 * ensure that we're not cross-dressing a TCP server into HTTP.
5175 */
5176 newsrv = curproxy->srv;
5177 while (newsrv != NULL) {
5178 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005179 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5180 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005181 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005182 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005183
Willy Tarreauefa5f512010-03-30 20:13:29 +02005184#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005185 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5186 newsrv->bind_hdr_occ = 0;
5187 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5188 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5189 err_code |= ERR_WARN;
5190 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005191#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005192 newsrv = newsrv->next;
5193 }
5194
5195 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 * If this server supports a maxconn parameter, it needs a dedicated
5197 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005198 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 */
5200 newsrv = curproxy->srv;
5201 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005202 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 /* Only 'minconn' was specified, or it was higher than or equal
5204 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5205 * this will avoid further useless expensive computations.
5206 */
5207 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005208 } else if (newsrv->maxconn && !newsrv->minconn) {
5209 /* minconn was not specified, so we set it to maxconn */
5210 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005211 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005212 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5213 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005214 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 }
5216
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005217 if (newsrv->trackit) {
5218 struct proxy *px;
5219 struct server *srv;
5220 char *pname, *sname;
5221
5222 pname = newsrv->trackit;
5223 sname = strrchr(pname, '/');
5224
5225 if (sname)
5226 *sname++ = '\0';
5227 else {
5228 sname = pname;
5229 pname = NULL;
5230 }
5231
5232 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005233 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005234 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005235 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5236 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005237 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005238 cfgerr++;
5239 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005240 }
5241 } else
5242 px = curproxy;
5243
5244 srv = findserver(px, sname);
5245 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005246 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5247 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005248 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005249 cfgerr++;
5250 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005251 }
5252
5253 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005254 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005255 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005256 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005257 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005258 cfgerr++;
5259 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005260 }
5261
5262 if (curproxy != px &&
5263 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005264 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005265 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005266 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005267 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005268 cfgerr++;
5269 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005270 }
5271
5272 newsrv->tracked = srv;
5273 newsrv->tracknext = srv->tracknext;
5274 srv->tracknext = newsrv;
5275
5276 free(newsrv->trackit);
5277 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005278 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 newsrv = newsrv->next;
5280 }
5281
Willy Tarreauc1a21672009-08-16 22:37:44 +02005282 if (curproxy->cap & PR_CAP_FE) {
5283 if (curproxy->tcp_req.inspect_delay ||
5284 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5285 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5286
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005287 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005288 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005289 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005290 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005291
5292 /* both TCP and HTTP must check switching rules */
5293 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5294 }
5295
5296 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005297 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005298 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005299 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005300 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005301
Emeric Brunb982a3d2010-01-04 15:45:53 +01005302 /* init table on backend capabilities proxy */
5303 stktable_init(&curproxy->table);
5304
Willy Tarreauc1a21672009-08-16 22:37:44 +02005305 /* If the backend does requires RDP cookie persistence, we have to
5306 * enable the corresponding analyser.
5307 */
5308 if (curproxy->options2 & PR_O2_RDPC_PRST)
5309 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5310 }
5311
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005312 listener = NULL;
5313 while (curproxy->listen) {
5314 struct listener *next;
5315
5316 next = curproxy->listen->next;
5317 curproxy->listen->next = listener;
5318 listener = curproxy->listen;
5319
5320 if (!next)
5321 break;
5322
5323 curproxy->listen = next;
5324 }
5325
Willy Tarreaue6b98942007-10-29 01:09:36 +01005326 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005327 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005328 listener = curproxy->listen;
5329 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005330 if (!listener->luid) {
5331 /* listener ID not set, use automatic numbering with first
5332 * spare entry starting with next_luid.
5333 */
5334 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5335 listener->conf.id.key = listener->luid = next_id;
5336 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005337 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005338 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005339
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005340 /* enable separate counters */
5341 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5342 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5343 if (!listener->name) {
5344 sprintf(trash, "sock-%d", listener->luid);
5345 listener->name = strdup(trash);
5346 }
5347 }
5348
Willy Tarreaue6b98942007-10-29 01:09:36 +01005349 if (curproxy->options & PR_O_TCP_NOLING)
5350 listener->options |= LI_O_NOLINGER;
5351 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005352 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005353 listener->timeout = &curproxy->timeout.client;
Willy Tarreaueb472682010-05-28 18:46:57 +02005354 listener->accept = frontend_accept;
5355 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005356 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005357 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005358
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02005359 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
5360 listener->options |= LI_O_TCP_RULES;
5361
Willy Tarreaude3041d2010-05-31 10:56:17 +02005362 if (curproxy->mon_mask.s_addr)
5363 listener->options |= LI_O_CHK_MONNET;
5364
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005365 /* smart accept mode is automatic in HTTP mode */
5366 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5367 (curproxy->mode == PR_MODE_HTTP &&
5368 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5369 listener->options |= LI_O_NOQUICKACK;
5370
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005371 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005372 listener = listener->next;
5373 }
5374
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 curproxy = curproxy->next;
5376 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005377
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005378 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5379 struct auth_users *curuser;
5380 int g;
5381
5382 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5383 unsigned int group_mask = 0;
5384 char *group = NULL;
5385
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005386 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005387 continue;
5388
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005389 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005390
5391 for (g = 0; g < curuserlist->grpcnt; g++)
5392 if (!strcmp(curuserlist->groups[g], group))
5393 break;
5394
5395 if (g == curuserlist->grpcnt) {
5396 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5397 curuserlist->name, group, curuser->user);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
5401
5402 group_mask |= (1 << g);
5403 }
5404
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005405 free(curuser->u.groups);
5406 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005407 }
5408
5409 for (g = 0; g < curuserlist->grpcnt; g++) {
5410 char *user = NULL;
5411
5412 if (!curuserlist->groupusers[g])
5413 continue;
5414
5415 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5416 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5417 if (!strcmp(curuser->user, user))
5418 break;
5419
5420 if (!curuser) {
5421 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5422 curuserlist->name, user, curuserlist->groups[g]);
5423 err_code |= ERR_ALERT | ERR_FATAL;
5424 goto out;
5425 }
5426
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005427 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005428 }
5429
5430 free(curuserlist->groupusers[g]);
5431 }
5432
5433 free(curuserlist->groupusers);
5434
5435#ifdef DEBUG_AUTH
5436 for (g = 0; g < curuserlist->grpcnt; g++) {
5437 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5438
5439 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5440 if (curuser->group_mask & (1 << g))
5441 fprintf(stderr, " %s", curuser->user);
5442 }
5443
5444 fprintf(stderr, "\n");
5445 }
5446#endif
5447
5448 }
5449
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005450 /*
5451 * Recount currently required checks.
5452 */
5453
5454 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5455 int optnum;
5456
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005457 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5458 if (curproxy->options & cfg_opts[optnum].val)
5459 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005460
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005461 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5462 if (curproxy->options2 & cfg_opts2[optnum].val)
5463 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005464 }
5465
Willy Tarreaubb925012009-07-23 13:36:36 +02005466 if (cfgerr > 0)
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 out:
5469 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470}
5471
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005472/*
5473 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5474 * parsing sessions.
5475 */
5476void cfg_register_keywords(struct cfg_kw_list *kwl)
5477{
5478 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5479}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005481/*
5482 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5483 */
5484void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5485{
5486 LIST_DEL(&kwl->list);
5487 LIST_INIT(&kwl->list);
5488}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489
5490/*
5491 * Local variables:
5492 * c-indent-level: 8
5493 * c-basic-offset: 8
5494 * End:
5495 */