blob: f313b71ec2221c98788c03a879750dee7e13e744 [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 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002277 else if (strcmp(args[myidx], "store") == 0) {
2278 int type;
2279
2280 myidx++;
2281 type = stktable_get_data_type(args[myidx]);
2282 if (type < 0) {
2283 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2284 file, linenum, args[0], args[myidx]);
2285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
2287 }
2288 if (!stktable_alloc_data_type(&curproxy->table, type)) {
2289 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2290 file, linenum, args[0], args[myidx]);
2291 err_code |= ERR_WARN;
2292 }
2293 myidx++;
2294 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002295 else {
2296 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2297 file, linenum, args[myidx]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002300 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002301 }
2302
2303 if (!curproxy->table.size) {
2304 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2305 file, linenum);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 if (curproxy->table.type == (unsigned int)-1) {
2311 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2312 file, linenum);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316 }
2317 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002318 struct sticking_rule *rule;
2319 struct pattern_expr *expr;
2320 int myidx = 0;
2321 const char *name = NULL;
2322 int flags;
2323
2324 if (curproxy == &defproxy) {
2325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329
2330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2331 err_code |= ERR_WARN;
2332 goto out;
2333 }
2334
2335 myidx++;
2336 if ((strcmp(args[myidx], "store") == 0) ||
2337 (strcmp(args[myidx], "store-request") == 0)) {
2338 myidx++;
2339 flags = STK_IS_STORE;
2340 }
2341 else if (strcmp(args[myidx], "store-response") == 0) {
2342 myidx++;
2343 flags = STK_IS_STORE | STK_ON_RSP;
2344 }
2345 else if (strcmp(args[myidx], "match") == 0) {
2346 myidx++;
2347 flags = STK_IS_MATCH;
2348 }
2349 else if (strcmp(args[myidx], "on") == 0) {
2350 myidx++;
2351 flags = STK_IS_MATCH | STK_IS_STORE;
2352 }
2353 else {
2354 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
2358
2359 if (*(args[myidx]) == 0) {
2360 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364
2365 expr = pattern_parse_expr(args, &myidx);
2366 if (!expr) {
2367 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
2370 }
2371
2372 if (flags & STK_ON_RSP) {
2373 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2374 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2375 file, linenum, args[0], expr->fetch->kw);
2376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
2378 }
2379 } else {
2380 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2381 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2382 file, linenum, args[0], expr->fetch->kw);
2383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
2385 }
2386 }
2387
2388 if (strcmp(args[myidx], "table") == 0) {
2389 myidx++;
2390 name = args[myidx++];
2391 }
2392
Willy Tarreauef6494c2010-01-28 17:12:36 +01002393 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2394 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002395 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2396 file, linenum, args[0]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002400 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002401 else if (*(args[myidx])) {
2402 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2403 file, linenum, args[0], args[myidx]);
2404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
2406 }
2407
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002408 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2409
Emeric Brunb982a3d2010-01-04 15:45:53 +01002410 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2411 rule->cond = cond;
2412 rule->expr = expr;
2413 rule->flags = flags;
2414 rule->table.name = name ? strdup(name) : NULL;
2415 LIST_INIT(&rule->list);
2416 if (flags & STK_ON_RSP)
2417 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2418 else
2419 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2426 curproxy->uri_auth = NULL; /* we must detach from the default config */
2427
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002428 if (!*args[1]) {
2429 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 } else if (!strcmp(args[1], "uri")) {
2431 if (*(args[2]) == 0) {
2432 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2436 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_ABORT;
2438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 }
2440 } else if (!strcmp(args[1], "realm")) {
2441 if (*(args[2]) == 0) {
2442 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2446 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002447 err_code |= ERR_ALERT | ERR_ABORT;
2448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002450 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002451 unsigned interval;
2452
2453 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2454 if (err) {
2455 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2456 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002459 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2460 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_ABORT;
2462 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002463 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002464 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2465 struct req_acl_rule *req_acl;
2466
2467 if (curproxy == &defproxy) {
2468 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472
2473 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2474 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2475 err_code |= ERR_ALERT | ERR_ABORT;
2476 goto out;
2477 }
2478
2479 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2480 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2481 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2482 file, linenum, args[0]);
2483 err_code |= ERR_WARN;
2484 }
2485
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002486 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002487
2488 if (!req_acl) {
2489 err_code |= ERR_ALERT | ERR_ABORT;
2490 goto out;
2491 }
2492
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002493 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002494 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2495
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 } else if (!strcmp(args[1], "auth")) {
2497 if (*(args[2]) == 0) {
2498 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2502 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002503 err_code |= ERR_ALERT | ERR_ABORT;
2504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 }
2506 } else if (!strcmp(args[1], "scope")) {
2507 if (*(args[2]) == 0) {
2508 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2512 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002513 err_code |= ERR_ALERT | ERR_ABORT;
2514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 }
2516 } else if (!strcmp(args[1], "enable")) {
2517 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2518 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_ABORT;
2520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002522 } else if (!strcmp(args[1], "hide-version")) {
2523 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2524 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_ABORT;
2526 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002527 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002528 } else if (!strcmp(args[1], "show-legends")) {
2529 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2530 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2531 err_code |= ERR_ALERT | ERR_ABORT;
2532 goto out;
2533 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002534 } else if (!strcmp(args[1], "show-node")) {
2535
2536 if (*args[2]) {
2537 int i;
2538 char c;
2539
2540 for (i=0; args[2][i]; i++) {
2541 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002542 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2543 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002544 break;
2545 }
2546
2547 if (!i || args[2][i]) {
2548 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2549 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2550 file, linenum, args[0], args[1]);
2551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
2553 }
2554 }
2555
2556 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2557 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2558 err_code |= ERR_ALERT | ERR_ABORT;
2559 goto out;
2560 }
2561 } else if (!strcmp(args[1], "show-desc")) {
2562 char *desc = NULL;
2563
2564 if (*args[2]) {
2565 int i, len=0;
2566 char *d;
2567
2568 for(i=2; *args[i]; i++)
2569 len += strlen(args[i])+1;
2570
2571 desc = d = (char *)calloc(1, len);
2572
2573 d += sprintf(d, "%s", args[2]);
2574 for(i=3; *args[i]; i++)
2575 d += sprintf(d, " %s", args[i]);
2576 }
2577
2578 if (!*args[2] && !global.desc)
2579 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2580 file, linenum, args[1]);
2581 else {
2582 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2583 free(desc);
2584 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2585 err_code |= ERR_ALERT | ERR_ABORT;
2586 goto out;
2587 }
2588 free(desc);
2589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002591stats_error_parsing:
2592 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2593 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597 }
2598 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002599 int optnum;
2600
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002601 if (*(args[1]) == '\0') {
2602 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002607
2608 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2609 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002610 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2611 err_code |= ERR_WARN;
2612 goto out;
2613 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002614
Willy Tarreau3842f002009-06-14 11:39:52 +02002615 curproxy->no_options &= ~cfg_opts[optnum].val;
2616 curproxy->options &= ~cfg_opts[optnum].val;
2617
2618 switch (kwm) {
2619 case KWM_STD:
2620 curproxy->options |= cfg_opts[optnum].val;
2621 break;
2622 case KWM_NO:
2623 curproxy->no_options |= cfg_opts[optnum].val;
2624 break;
2625 case KWM_DEF: /* already cleared */
2626 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002627 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002628
Willy Tarreau93893792009-07-23 13:19:11 +02002629 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002630 }
2631 }
2632
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002633 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2634 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002635 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2636 err_code |= ERR_WARN;
2637 goto out;
2638 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002639
Willy Tarreau3842f002009-06-14 11:39:52 +02002640 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2641 curproxy->options2 &= ~cfg_opts2[optnum].val;
2642
2643 switch (kwm) {
2644 case KWM_STD:
2645 curproxy->options2 |= cfg_opts2[optnum].val;
2646 break;
2647 case KWM_NO:
2648 curproxy->no_options2 |= cfg_opts2[optnum].val;
2649 break;
2650 case KWM_DEF: /* already cleared */
2651 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002652 }
Willy Tarreau93893792009-07-23 13:19:11 +02002653 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002654 }
2655 }
2656
Willy Tarreau3842f002009-06-14 11:39:52 +02002657 if (kwm != KWM_STD) {
2658 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002659 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002662 }
2663
Emeric Brun3a058f32009-06-30 18:26:00 +02002664 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002666 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002668 if (*(args[2]) != '\0') {
2669 if (!strcmp(args[2], "clf")) {
2670 curproxy->options2 |= PR_O2_CLFLOG;
2671 } else {
2672 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002675 }
2676 }
2677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 else if (!strcmp(args[1], "tcplog"))
2679 /* generate a detailed TCP log */
2680 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 else if (!strcmp(args[1], "tcpka")) {
2682 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002683 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002684 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002685
2686 if (curproxy->cap & PR_CAP_FE)
2687 curproxy->options |= PR_O_TCP_CLI_KA;
2688 if (curproxy->cap & PR_CAP_BE)
2689 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 }
2691 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_WARN;
2694
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002696 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002697 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002698 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002699 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002700 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002701 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 if (!*args[2]) { /* no argument */
2703 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2704 curproxy->check_len = strlen(DEF_CHECK_REQ);
2705 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002706 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 curproxy->check_req = (char *)malloc(reqlen);
2708 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002709 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002711 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 if (*args[4])
2713 reqlen += strlen(args[4]);
2714 else
2715 reqlen += strlen("HTTP/1.0");
2716
2717 curproxy->check_req = (char *)malloc(reqlen);
2718 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002719 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002721 }
2722 else if (!strcmp(args[1], "ssl-hello-chk")) {
2723 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002724 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002726
Willy Tarreaua534fea2008-08-03 12:19:50 +02002727 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002728 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002729 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002730 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002731 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002732 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733 }
Willy Tarreau23677902007-05-08 23:50:35 +02002734 else if (!strcmp(args[1], "smtpchk")) {
2735 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002736 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002737 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002738 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002739 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002740 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002741 curproxy->options |= PR_O_SMTP_CHK;
2742
2743 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2744 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2745 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2746 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2747 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2748 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2749 curproxy->check_req = (char *)malloc(reqlen);
2750 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2751 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2752 } else {
2753 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2754 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2755 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2756 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2757 }
2758 }
2759 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002760 else if (!strcmp(args[1], "mysql-check")) {
2761 /* use MYSQL request to check servers' health */
2762 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002763 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002764 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002765 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002766 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002767 curproxy->options2 |= PR_O2_MYSQL_CHK;
2768 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002769 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002770 int cur_arg;
2771
2772 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2773 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002774 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002775
2776 curproxy->options |= PR_O_FWDFOR;
2777
2778 free(curproxy->fwdfor_hdr_name);
2779 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2780 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2781
2782 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2783 cur_arg = 2;
2784 while (*(args[cur_arg])) {
2785 if (!strcmp(args[cur_arg], "except")) {
2786 /* suboption except - needs additional argument for it */
2787 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2788 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2789 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002792 }
2793 /* flush useless bits */
2794 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002795 cur_arg += 2;
2796 } else if (!strcmp(args[cur_arg], "header")) {
2797 /* suboption header - needs additional argument for it */
2798 if (*(args[cur_arg+1]) == 0) {
2799 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2800 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002803 }
2804 free(curproxy->fwdfor_hdr_name);
2805 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2806 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2807 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002808 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002809 /* unknown suboption - catchall */
2810 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2811 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002814 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002815 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002816 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002817 else if (!strcmp(args[1], "originalto")) {
2818 int cur_arg;
2819
2820 /* insert x-original-to field, but not for the IP address listed as an except.
2821 * set default options (ie: bitfield, header name, etc)
2822 */
2823
2824 curproxy->options |= PR_O_ORGTO;
2825
2826 free(curproxy->orgto_hdr_name);
2827 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2828 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2829
2830 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2831 cur_arg = 2;
2832 while (*(args[cur_arg])) {
2833 if (!strcmp(args[cur_arg], "except")) {
2834 /* suboption except - needs additional argument for it */
2835 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2836 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2837 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002840 }
2841 /* flush useless bits */
2842 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2843 cur_arg += 2;
2844 } else if (!strcmp(args[cur_arg], "header")) {
2845 /* suboption header - needs additional argument for it */
2846 if (*(args[cur_arg+1]) == 0) {
2847 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2848 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002851 }
2852 free(curproxy->orgto_hdr_name);
2853 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2854 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2855 cur_arg += 2;
2856 } else {
2857 /* unknown suboption - catchall */
2858 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2859 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002862 }
2863 } /* end while loop */
2864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 else {
2866 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 }
Willy Tarreau93893792009-07-23 13:19:11 +02002870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002872 else if (!strcmp(args[0], "default_backend")) {
2873 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002875
2876 if (*(args[1]) == 0) {
2877 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002880 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002881 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002882 curproxy->defbe.name = strdup(args[1]);
2883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002885 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002888 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2889 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 /* enable reconnections to dispatch */
2892 curproxy->options |= PR_O_REDISP;
2893 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002894 else if (!strcmp(args[0], "http-check")) {
2895 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002896 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002897
2898 if (strcmp(args[1], "disable-on-404") == 0) {
2899 /* enable a graceful server shutdown on an HTTP 404 response */
2900 curproxy->options |= PR_O_DISABLE404;
2901 }
Willy Tarreauef781042010-01-27 11:53:01 +01002902 else if (strcmp(args[1], "send-state") == 0) {
2903 /* enable emission of the apparent state of a server in HTTP checks */
2904 curproxy->options2 |= PR_O2_CHK_SNDST;
2905 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002906 else {
2907 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002908 err_code |= ERR_ALERT | ERR_FATAL;
2909 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002910 }
2911 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002912 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002913 if (curproxy == &defproxy) {
2914 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002917 }
2918
Willy Tarreaub80c2302007-11-30 20:51:32 +01002919 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002921
2922 if (strcmp(args[1], "fail") == 0) {
2923 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002924 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002925 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2926 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002929 }
2930
Willy Tarreauef6494c2010-01-28 17:12:36 +01002931 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002932 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2933 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002936 }
2937 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2938 }
2939 else {
2940 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002943 }
2944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945#ifdef TPROXY
2946 else if (!strcmp(args[0], "transparent")) {
2947 /* enable transparent proxy connections */
2948 curproxy->options |= PR_O_TRANSP;
2949 }
2950#endif
2951 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002952 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002953 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002954
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 if (*(args[1]) == 0) {
2956 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002957 err_code |= ERR_ALERT | ERR_FATAL;
2958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002959 }
2960 curproxy->maxconn = atol(args[1]);
2961 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002962 else if (!strcmp(args[0], "backlog")) { /* backlog */
2963 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002965
2966 if (*(args[1]) == 0) {
2967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002970 }
2971 curproxy->backlog = atol(args[1]);
2972 }
Willy Tarreau86034312006-12-29 00:10:33 +01002973 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976
Willy Tarreau86034312006-12-29 00:10:33 +01002977 if (*(args[1]) == 0) {
2978 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002981 }
2982 curproxy->fullconn = atol(args[1]);
2983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2985 if (*(args[1]) == 0) {
2986 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002990 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2991 if (err) {
2992 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2993 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002996 }
2997 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
2999 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003000 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 if (curproxy == &defproxy) {
3002 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003006 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 if (strchr(args[1], ':') == NULL) {
3010 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003014 sk = str2sa(args[1]);
3015 if (!sk) {
3016 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 }
3022 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003026 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003027 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3028 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003033 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3034 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3035 err_code |= ERR_WARN;
3036
3037 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3038 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3039 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3040 }
3041 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3042 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3043 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3044 }
3045 else {
3046 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
3049 }
3050 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003051 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003053 char *rport, *raddr;
3054 short realport = 0;
3055 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003057 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003062 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064
3065 if (!*args[2]) {
3066 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003071
3072 err = invalid_char(args[1]);
3073 if (err) {
3074 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3075 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003078 }
3079
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003080 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003081 struct sockaddr_in *sk;
3082
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003083 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3084 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3085 err_code |= ERR_ALERT | ERR_ABORT;
3086 goto out;
3087 }
3088
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003089 /* the servers are linked backwards first */
3090 newsrv->next = curproxy->srv;
3091 curproxy->srv = newsrv;
3092 newsrv->proxy = curproxy;
3093 newsrv->conf.file = file;
3094 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003096 LIST_INIT(&newsrv->pendconns);
3097 do_check = 0;
3098 newsrv->state = SRV_RUNNING; /* early server setup */
3099 newsrv->last_change = now.tv_sec;
3100 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003102 /* several ways to check the port component :
3103 * - IP => port=+0, relative
3104 * - IP: => port=+0, relative
3105 * - IP:N => port=N, absolute
3106 * - IP:+N => port=+N, relative
3107 * - IP:-N => port=-N, relative
3108 */
3109 raddr = strdup(args[2]);
3110 rport = strchr(raddr, ':');
3111 if (rport) {
3112 *rport++ = 0;
3113 realport = atol(rport);
3114 if (!isdigit((unsigned char)*rport))
3115 newsrv->state |= SRV_MAPPORTS;
3116 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003118
Willy Tarreaud5191e72010-02-09 20:50:45 +01003119 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003120 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003121 if (!sk) {
3122 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
3126 newsrv->addr = *sk;
3127 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003128
3129 newsrv->check_port = curproxy->defsrv.check_port;
3130 newsrv->inter = curproxy->defsrv.inter;
3131 newsrv->fastinter = curproxy->defsrv.fastinter;
3132 newsrv->downinter = curproxy->defsrv.downinter;
3133 newsrv->rise = curproxy->defsrv.rise;
3134 newsrv->fall = curproxy->defsrv.fall;
3135 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3136 newsrv->minconn = curproxy->defsrv.minconn;
3137 newsrv->maxconn = curproxy->defsrv.maxconn;
3138 newsrv->slowstart = curproxy->defsrv.slowstart;
3139 newsrv->onerror = curproxy->defsrv.onerror;
3140 newsrv->consecutive_errors_limit
3141 = curproxy->defsrv.consecutive_errors_limit;
3142 newsrv->uweight = newsrv->iweight
3143 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003145 newsrv->curfd = -1; /* no health-check in progress */
3146 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003148 cur_arg = 3;
3149 } else {
3150 newsrv = &curproxy->defsrv;
3151 cur_arg = 1;
3152 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003153
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003155 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003156 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003157
3158 if (!*args[cur_arg + 1]) {
3159 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3160 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003163 }
3164
3165 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003166 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003167
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003168 if (newsrv->puid <= 0) {
3169 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003170 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003173 }
3174
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003175 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3176 if (node) {
3177 struct server *target = container_of(node, struct server, conf.id);
3178 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3179 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003184 cur_arg += 2;
3185 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003186 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 newsrv->cookie = strdup(args[cur_arg + 1]);
3188 newsrv->cklen = strlen(args[cur_arg + 1]);
3189 cur_arg += 2;
3190 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003191 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003192 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3193 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3194 cur_arg += 2;
3195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003197 if (!*args[cur_arg + 1]) {
3198 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3199 file, linenum, args[cur_arg]);
3200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
3202 }
3203
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003205 if (newsrv->rise <= 0) {
3206 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3207 file, linenum, args[cur_arg]);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
3210 }
3211
Willy Tarreau96839092010-03-29 10:02:24 +02003212 if (newsrv->health)
3213 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 cur_arg += 2;
3215 }
3216 else if (!strcmp(args[cur_arg], "fall")) {
3217 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003218
3219 if (!*args[cur_arg + 1]) {
3220 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3221 file, linenum, args[cur_arg]);
3222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
3225
3226 if (newsrv->fall <= 0) {
3227 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3228 file, linenum, args[cur_arg]);
3229 err_code |= ERR_ALERT | ERR_FATAL;
3230 goto out;
3231 }
3232
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 cur_arg += 2;
3234 }
3235 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003236 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3237 if (err) {
3238 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3239 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003242 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003243 if (val <= 0) {
3244 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3245 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003248 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003249 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 cur_arg += 2;
3251 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003252 else if (!strcmp(args[cur_arg], "fastinter")) {
3253 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3254 if (err) {
3255 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3256 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003259 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003260 if (val <= 0) {
3261 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3262 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003265 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003266 newsrv->fastinter = val;
3267 cur_arg += 2;
3268 }
3269 else if (!strcmp(args[cur_arg], "downinter")) {
3270 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3271 if (err) {
3272 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3273 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003276 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003277 if (val <= 0) {
3278 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3279 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003282 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003283 newsrv->downinter = val;
3284 cur_arg += 2;
3285 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003286 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003287 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3288 if (!sk) {
3289 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
3293 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003294 cur_arg += 2;
3295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 else if (!strcmp(args[cur_arg], "port")) {
3297 newsrv->check_port = atol(args[cur_arg + 1]);
3298 cur_arg += 2;
3299 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003300 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 newsrv->state |= SRV_BACKUP;
3302 cur_arg ++;
3303 }
3304 else if (!strcmp(args[cur_arg], "weight")) {
3305 int w;
3306 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003307 if (w < 0 || w > 256) {
3308 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003313 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 cur_arg += 2;
3315 }
3316 else if (!strcmp(args[cur_arg], "minconn")) {
3317 newsrv->minconn = atol(args[cur_arg + 1]);
3318 cur_arg += 2;
3319 }
3320 else if (!strcmp(args[cur_arg], "maxconn")) {
3321 newsrv->maxconn = atol(args[cur_arg + 1]);
3322 cur_arg += 2;
3323 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003324 else if (!strcmp(args[cur_arg], "maxqueue")) {
3325 newsrv->maxqueue = atol(args[cur_arg + 1]);
3326 cur_arg += 2;
3327 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003328 else if (!strcmp(args[cur_arg], "slowstart")) {
3329 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003330 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003331 if (err) {
3332 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3333 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003336 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003337 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003338 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3339 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003342 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003343 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003344 cur_arg += 2;
3345 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003346 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003347
3348 if (!*args[cur_arg + 1]) {
3349 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3350 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003353 }
3354
3355 newsrv->trackit = strdup(args[cur_arg + 1]);
3356
3357 cur_arg += 2;
3358 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003359 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 global.maxsock++;
3361 do_check = 1;
3362 cur_arg += 1;
3363 }
Willy Tarreau96839092010-03-29 10:02:24 +02003364 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3365 newsrv->state |= SRV_MAINTAIN;
3366 newsrv->state &= ~SRV_RUNNING;
3367 newsrv->health = 0;
3368 cur_arg += 1;
3369 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003370 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003371 if (!strcmp(args[cur_arg + 1], "none"))
3372 newsrv->observe = HANA_OBS_NONE;
3373 else if (!strcmp(args[cur_arg + 1], "layer4"))
3374 newsrv->observe = HANA_OBS_LAYER4;
3375 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3376 if (curproxy->mode != PR_MODE_HTTP) {
3377 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3378 file, linenum, args[cur_arg + 1]);
3379 err_code |= ERR_ALERT;
3380 }
3381 newsrv->observe = HANA_OBS_LAYER7;
3382 }
3383 else {
3384 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3385 "'l4events', 'http-responses' but get '%s'\n",
3386 file, linenum, args[cur_arg], args[cur_arg + 1]);
3387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
3389 }
3390
3391 cur_arg += 2;
3392 }
3393 else if (!strcmp(args[cur_arg], "on-error")) {
3394 if (!strcmp(args[cur_arg + 1], "fastinter"))
3395 newsrv->onerror = HANA_ONERR_FASTINTER;
3396 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3397 newsrv->onerror = HANA_ONERR_FAILCHK;
3398 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3399 newsrv->onerror = HANA_ONERR_SUDDTH;
3400 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3401 newsrv->onerror = HANA_ONERR_MARKDWN;
3402 else {
3403 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3404 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3405 file, linenum, args[cur_arg], args[cur_arg + 1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409
3410 cur_arg += 2;
3411 }
3412 else if (!strcmp(args[cur_arg], "error-limit")) {
3413 if (!*args[cur_arg + 1]) {
3414 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3415 file, linenum, args[cur_arg]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
3420 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3421
3422 if (newsrv->consecutive_errors_limit <= 0) {
3423 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3424 file, linenum, args[cur_arg]);
3425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
3427 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003428 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003429 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003430 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003431 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003432 struct sockaddr_in *sk;
3433
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003435#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003436 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003437 file, linenum, "source", "usesrc");
3438#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003439 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003441#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 }
3445 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003446 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3447 if (!sk) {
3448 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
3451 }
3452 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003453
3454 if (port_low != port_high) {
3455 int i;
3456 if (port_low <= 0 || port_low > 65535 ||
3457 port_high <= 0 || port_high > 65535 ||
3458 port_low > port_high) {
3459 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3460 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003463 }
3464 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3465 for (i = 0; i < newsrv->sport_range->size; i++)
3466 newsrv->sport_range->ports[i] = port_low + i;
3467 }
3468
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003470 while (*(args[cur_arg])) {
3471 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003472#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3473#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003474 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3475 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3476 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003479 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003480#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003481 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003482 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01003483 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003486 }
3487 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003488 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003489 newsrv->state |= SRV_TPROXY_CLI;
3490 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003491 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003492 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003493 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3494 char *name, *end;
3495
3496 name = args[cur_arg+1] + 7;
3497 while (isspace(*name))
3498 name++;
3499
3500 end = name;
3501 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3502 end++;
3503
3504 newsrv->state &= ~SRV_TPROXY_MASK;
3505 newsrv->state |= SRV_TPROXY_DYN;
3506 newsrv->bind_hdr_name = calloc(1, end - name + 1);
3507 newsrv->bind_hdr_len = end - name;
3508 memcpy(newsrv->bind_hdr_name, name, end - name);
3509 newsrv->bind_hdr_name[end-name] = '\0';
3510 newsrv->bind_hdr_occ = -1;
3511
3512 /* now look for an occurrence number */
3513 while (isspace(*end))
3514 end++;
3515 if (*end == ',') {
3516 end++;
3517 name = end;
3518 if (*end == '-')
3519 end++;
3520 while (isdigit(*end))
3521 end++;
3522 newsrv->bind_hdr_occ = strl2ic(name, end-name);
3523 }
3524
3525 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
3526 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3527 " occurrences values smaller than %d.\n",
3528 file, linenum, MAX_HDR_HISTORY);
3529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
3531 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01003532 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003533 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3534 if (!sk) {
3535 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003540 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003541 }
3542 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003543#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003544 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003545#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003546 cur_arg += 2;
3547 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003548#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003549 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003550 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003553#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3554 } /* "usesrc" */
3555
3556 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3557#ifdef SO_BINDTODEVICE
3558 if (!*args[cur_arg + 1]) {
3559 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3560 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003563 }
3564 if (newsrv->iface_name)
3565 free(newsrv->iface_name);
3566
3567 newsrv->iface_name = strdup(args[cur_arg + 1]);
3568 newsrv->iface_len = strlen(newsrv->iface_name);
3569 global.last_checks |= LSTCHK_NETADM;
3570#else
3571 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3572 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003575#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003576 cur_arg += 2;
3577 continue;
3578 }
3579 /* this keyword in not an option of "source" */
3580 break;
3581 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003583 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003584 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3585 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003590 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003591 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 +01003592 file, linenum, newsrv->id);
3593 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003594 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 +01003595 file, linenum);
3596
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 }
3600 }
3601
3602 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003603 if (newsrv->trackit) {
3604 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3605 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003608 }
3609
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003610 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3611 newsrv->check_port = newsrv->check_addr.sin_port;
3612
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3614 newsrv->check_port = realport; /* by default */
3615 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003616 /* not yet valid, because no port was set on
3617 * the server either. We'll check if we have
3618 * a known port on the first listener.
3619 */
3620 struct listener *l;
3621 l = curproxy->listen;
3622 if (l) {
3623 int port;
3624 port = (l->addr.ss_family == AF_INET6)
3625 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3626 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3627 newsrv->check_port = port;
3628 }
3629 }
3630 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3632 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003636
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003637 /* Allocate buffer for partial check results... */
3638 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3639 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3640 err_code |= ERR_ALERT | ERR_ABORT;
3641 goto out;
3642 }
3643
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003644 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 newsrv->state |= SRV_CHECKED;
3646 }
3647
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003648 if (!defsrv) {
3649 if (newsrv->state & SRV_BACKUP)
3650 curproxy->srv_bck++;
3651 else
3652 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003653
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003654 newsrv->prev_state = newsrv->state;
3655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
3657 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003658 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 int facility;
3660
3661 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3662 curproxy->logfac1 = global.logfac1;
3663 curproxy->logsrv1 = global.logsrv1;
3664 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003665 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 curproxy->logfac2 = global.logfac2;
3667 curproxy->logsrv2 = global.logsrv2;
3668 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003669 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 }
3671 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003672 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673
3674 facility = get_log_facility(args[2]);
3675 if (facility < 0) {
3676 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3677 exit(1);
3678 }
3679
3680 level = 7; /* max syslog level = debug */
3681 if (*(args[3])) {
3682 level = get_log_level(args[3]);
3683 if (level < 0) {
3684 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3685 exit(1);
3686 }
3687 }
3688
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003689 minlvl = 0; /* limit syslog level to this level (emerg) */
3690 if (*(args[4])) {
3691 minlvl = get_log_level(args[4]);
3692 if (level < 0) {
3693 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3694 exit(1);
3695 }
3696 }
3697
Robert Tsai81ae1952007-12-05 10:47:29 +01003698 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003699 struct sockaddr_un *sk = str2sun(args[1]);
3700 if (!sk) {
3701 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3702 args[1], (int)sizeof(sk->sun_path) - 1);
3703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
3705 }
3706 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003707 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003708 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003709 struct sockaddr_in *sk = str2sa(args[1]);
3710 if (!sk) {
3711 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003716 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003717 if (!logsrv.u.in.sin_port) {
3718 logsrv.u.in.sin_port =
3719 htons(SYSLOG_PORT);
3720 }
3721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722
3723 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003724 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 curproxy->logfac1 = facility;
3726 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003727 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
3729 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003730 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 curproxy->logfac2 = facility;
3732 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003733 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 }
3735 else {
3736 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 }
3740 }
3741 else {
3742 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3743 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 }
3747 }
3748 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003749 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003750 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003751
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003754
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003756 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3757 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003761
3762 /* we must first clear any optional default setting */
3763 curproxy->options &= ~PR_O_TPXY_MASK;
3764 free(curproxy->iface_name);
3765 curproxy->iface_name = NULL;
3766 curproxy->iface_len = 0;
3767
Willy Tarreaud5191e72010-02-09 20:50:45 +01003768 sk = str2sa(args[1]);
3769 if (!sk) {
3770 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
3774 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003776
3777 cur_arg = 2;
3778 while (*(args[cur_arg])) {
3779 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003780#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3781#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003782 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3783 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3784 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003787 }
3788#endif
3789 if (!*args[cur_arg + 1]) {
3790 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3791 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003794 }
3795
3796 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003797 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003798 curproxy->options |= PR_O_TPXY_CLI;
3799 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003800 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003801 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003802 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3803 char *name, *end;
3804
3805 name = args[cur_arg+1] + 7;
3806 while (isspace(*name))
3807 name++;
3808
3809 end = name;
3810 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3811 end++;
3812
3813 curproxy->options &= ~PR_O_TPXY_MASK;
3814 curproxy->options |= PR_O_TPXY_DYN;
3815 curproxy->bind_hdr_name = calloc(1, end - name + 1);
3816 curproxy->bind_hdr_len = end - name;
3817 memcpy(curproxy->bind_hdr_name, name, end - name);
3818 curproxy->bind_hdr_name[end-name] = '\0';
3819 curproxy->bind_hdr_occ = -1;
3820
3821 /* now look for an occurrence number */
3822 while (isspace(*end))
3823 end++;
3824 if (*end == ',') {
3825 end++;
3826 name = end;
3827 if (*end == '-')
3828 end++;
3829 while (isdigit(*end))
3830 end++;
3831 curproxy->bind_hdr_occ = strl2ic(name, end-name);
3832 }
3833
3834 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
3835 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3836 " occurrences values smaller than %d.\n",
3837 file, linenum, MAX_HDR_HISTORY);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003841 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003842 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3843 if (!sk) {
3844 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003849 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003850 }
3851 global.last_checks |= LSTCHK_NETADM;
3852#if !defined(CONFIG_HAP_LINUX_TPROXY)
3853 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003854#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003855#else /* no TPROXY support */
3856 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003857 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003860#endif
3861 cur_arg += 2;
3862 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003863 }
3864
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003865 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3866#ifdef SO_BINDTODEVICE
3867 if (!*args[cur_arg + 1]) {
3868 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003872 }
3873 if (curproxy->iface_name)
3874 free(curproxy->iface_name);
3875
3876 curproxy->iface_name = strdup(args[cur_arg + 1]);
3877 curproxy->iface_len = strlen(curproxy->iface_name);
3878 global.last_checks |= LSTCHK_NETADM;
3879#else
3880 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3881 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003884#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003885 cur_arg += 2;
3886 continue;
3887 }
3888 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3889 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003894 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3895 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3896 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003901 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3903 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003907
3908 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3909 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003910 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003911 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003913 }
3914 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003915 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3916 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003917 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003918 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003920 }
3921 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003922 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3923 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003924 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003925 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 }
3928 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003929 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3930 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003931 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003932 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 }
3935 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003936 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3937 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003938 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003939 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003942 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003943 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3944 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003945 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003946 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003947 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003948 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003949 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003950 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3951 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003952 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003953 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003954 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003955 }
3956 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003957 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3958 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003959 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003960 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003961 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003964 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003970
3971 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3972 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003973 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003974 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 }
3977 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003978 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3979 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003980 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003981 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 }
3984 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003985 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3986 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003987 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003988 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 }
3991 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003992 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3993 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003994 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003995 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 }
3998 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003999 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4000 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004001 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004002 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004005 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004006 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4007 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004008 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004010 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004013 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004014
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 if (curproxy == &defproxy) {
4016 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004020 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 if (*(args[1]) == 0) {
4024 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004028
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004029 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4030 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4031 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4032 file, linenum, args[0]);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4037 }
4038 else if (*args[2]) {
4039 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4040 file, linenum, args[0], args[2]);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004045 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004046 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004047 wl->s = strdup(args[1]);
4048 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004049 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 }
4051 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004052 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4054 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004058
Willy Tarreauade5ec42010-01-28 19:33:49 +01004059 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4060 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004061 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004062 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 }
4065 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004066 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4067 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004068 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004069 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071 }
4072 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004073 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4074 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004075 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004076 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 }
4079 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004080 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4082 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004085 }
4086
Willy Tarreauade5ec42010-01-28 19:33:49 +01004087 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4088 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004089 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004090 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 }
4093 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004094 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4095 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004096 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004097 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 }
4100 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004101 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4102 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004103 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004104 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106 }
4107 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004108 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004109
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 if (curproxy == &defproxy) {
4111 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004115 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118 if (*(args[1]) == 0) {
4119 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 }
4123
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004124 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4125 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4126 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4127 file, linenum, args[0]);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 err_code |= warnif_cond_requires_req(cond, file, linenum);
4132 }
4133 else if (*args[2]) {
4134 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4135 file, linenum, args[0], args[2]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
4139
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004140 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004141 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004142 wl->s = strdup(args[1]);
4143 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 }
4145 else if (!strcmp(args[0], "errorloc") ||
4146 !strcmp(args[0], "errorloc302") ||
4147 !strcmp(args[0], "errorloc303")) { /* error location */
4148 int errnum, errlen;
4149 char *err;
4150
Willy Tarreau977b8e42006-12-29 14:19:17 +01004151 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004153
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004155 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 }
4159
4160 errnum = atol(args[1]);
4161 if (!strcmp(args[0], "errorloc303")) {
4162 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4163 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4164 } else {
4165 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4166 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4167 }
4168
Willy Tarreau0f772532006-12-23 20:51:41 +01004169 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4170 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004171 chunk_destroy(&curproxy->errmsg[rc]);
4172 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004173 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004176
4177 if (rc >= HTTP_ERR_SIZE) {
4178 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4179 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 free(err);
4181 }
4182 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004183 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4184 int errnum, errlen, fd;
4185 char *err;
4186 struct stat stat;
4187
4188 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004190
4191 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004192 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004195 }
4196
4197 fd = open(args[2], O_RDONLY);
4198 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4199 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4200 file, linenum, args[2], args[1]);
4201 if (fd >= 0)
4202 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004205 }
4206
Willy Tarreau27a674e2009-08-17 07:23:33 +02004207 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004208 errlen = stat.st_size;
4209 } else {
4210 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004211 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004213 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004214 }
4215
4216 err = malloc(errlen); /* malloc() must succeed during parsing */
4217 errnum = read(fd, err, errlen);
4218 if (errnum != errlen) {
4219 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4220 file, linenum, args[2], args[1]);
4221 close(fd);
4222 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004225 }
4226 close(fd);
4227
4228 errnum = atol(args[1]);
4229 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4230 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004231 chunk_destroy(&curproxy->errmsg[rc]);
4232 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004233 break;
4234 }
4235 }
4236
4237 if (rc >= HTTP_ERR_SIZE) {
4238 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4239 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004241 free(err);
4242 }
4243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004245 struct cfg_kw_list *kwl;
4246 int index;
4247
4248 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4249 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4250 if (kwl->kw[index].section != CFG_LISTEN)
4251 continue;
4252 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4253 /* prepare error message just in case */
4254 snprintf(trash, sizeof(trash),
4255 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004256 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4257 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004258 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004261 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004262 else if (rc > 0) {
4263 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004264 err_code |= ERR_WARN;
4265 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004266 }
Willy Tarreau93893792009-07-23 13:19:11 +02004267 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004268 }
4269 }
4270 }
4271
Willy Tarreau6daf3432008-01-22 16:44:08 +01004272 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004275 }
Willy Tarreau93893792009-07-23 13:19:11 +02004276 out:
4277 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278}
4279
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004280int
4281cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4282{
4283
4284 int err_code = 0;
4285 const char *err;
4286
4287 if (!strcmp(args[0], "userlist")) { /* new userlist */
4288 struct userlist *newul;
4289
4290 if (!*args[1]) {
4291 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4292 file, linenum, args[0]);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296
4297 err = invalid_char(args[1]);
4298 if (err) {
4299 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4300 file, linenum, *err, args[0], args[1]);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
4304
4305 for (newul = userlist; newul; newul = newul->next)
4306 if (!strcmp(newul->name, args[1])) {
4307 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4308 file, linenum, args[1]);
4309 err_code |= ERR_WARN;
4310 goto out;
4311 }
4312
4313 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4314 if (!newul) {
4315 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4316 err_code |= ERR_ALERT | ERR_ABORT;
4317 goto out;
4318 }
4319
4320 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4321 newul->name = strdup(args[1]);
4322
4323 if (!newul->groupusers | !newul->name) {
4324 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4325 err_code |= ERR_ALERT | ERR_ABORT;
4326 goto out;
4327 }
4328
4329 newul->next = userlist;
4330 userlist = newul;
4331
4332 } else if (!strcmp(args[0], "group")) { /* new group */
4333 int cur_arg, i;
4334 const char *err;
4335
4336 if (!*args[1]) {
4337 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4338 file, linenum, args[0]);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
4342
4343 err = invalid_char(args[1]);
4344 if (err) {
4345 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4346 file, linenum, *err, args[0], args[1]);
4347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
4349 }
4350
4351 for(i = 0; i < userlist->grpcnt; i++)
4352 if (!strcmp(userlist->groups[i], args[1])) {
4353 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4354 file, linenum, args[1], userlist->name);
4355 err_code |= ERR_ALERT;
4356 goto out;
4357 }
4358
4359 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4360 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4361 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365
4366 cur_arg = 2;
4367
4368 while (*args[cur_arg]) {
4369 if (!strcmp(args[cur_arg], "users")) {
4370 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4371 cur_arg += 2;
4372 continue;
4373 } else {
4374 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4375 file, linenum, args[0]);
4376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
4378 }
4379 }
4380
4381 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4382 } else if (!strcmp(args[0], "user")) { /* new user */
4383 struct auth_users *newuser;
4384 int cur_arg;
4385
4386 if (!*args[1]) {
4387 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4388 file, linenum, args[0]);
4389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
4392
4393 for (newuser = userlist->users; newuser; newuser = newuser->next)
4394 if (!strcmp(newuser->user, args[1])) {
4395 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4396 file, linenum, args[1], userlist->name);
4397 err_code |= ERR_ALERT;
4398 goto out;
4399 }
4400
4401 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4402 if (!newuser) {
4403 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4404 err_code |= ERR_ALERT | ERR_ABORT;
4405 goto out;
4406 }
4407
4408 newuser->user = strdup(args[1]);
4409
4410 newuser->next = userlist->users;
4411 userlist->users = newuser;
4412
4413 cur_arg = 2;
4414
4415 while (*args[cur_arg]) {
4416 if (!strcmp(args[cur_arg], "password")) {
4417#ifndef CONFIG_HAP_CRYPT
4418 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4419 file, linenum);
4420 err_code |= ERR_ALERT;
4421#endif
4422 newuser->pass = strdup(args[cur_arg + 1]);
4423 cur_arg += 2;
4424 continue;
4425 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4426 newuser->pass = strdup(args[cur_arg + 1]);
4427 newuser->flags |= AU_O_INSECURE;
4428 cur_arg += 2;
4429 continue;
4430 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004431 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004432 cur_arg += 2;
4433 continue;
4434 } else {
4435 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4436 file, linenum, args[0]);
4437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
4439 }
4440 }
4441 } else {
4442 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4443 err_code |= ERR_ALERT | ERR_FATAL;
4444 }
4445
4446out:
4447 return err_code;
4448}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449
4450/*
4451 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004452 * Returns the error code, 0 if OK, or any combination of :
4453 * - ERR_ABORT: must abort ASAP
4454 * - ERR_FATAL: we can continue parsing but not start the service
4455 * - ERR_WARN: a warning has been emitted
4456 * - ERR_ALERT: an alert has been emitted
4457 * Only the two first ones can stop processing, the two others are just
4458 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004460int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004462 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 FILE *f;
4464 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004466 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 if ((f=fopen(file,"r")) == NULL)
4469 return -1;
4470
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004471 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004472 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004473 char *end;
4474 char *args[MAX_LINE_ARGS + 1];
4475 char *line = thisline;
4476
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 linenum++;
4478
4479 end = line + strlen(line);
4480
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004481 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4482 /* Check if we reached the limit and the last char is not \n.
4483 * Watch out for the last line without the terminating '\n'!
4484 */
4485 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004486 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004488 }
4489
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004491 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 line++;
4493
4494 arg = 0;
4495 args[arg] = line;
4496
4497 while (*line && arg < MAX_LINE_ARGS) {
4498 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4499 * C equivalent value. Other combinations left unchanged (eg: \1).
4500 */
4501 if (*line == '\\') {
4502 int skip = 0;
4503 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4504 *line = line[1];
4505 skip = 1;
4506 }
4507 else if (line[1] == 'r') {
4508 *line = '\r';
4509 skip = 1;
4510 }
4511 else if (line[1] == 'n') {
4512 *line = '\n';
4513 skip = 1;
4514 }
4515 else if (line[1] == 't') {
4516 *line = '\t';
4517 skip = 1;
4518 }
4519 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004520 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 unsigned char hex1, hex2;
4522 hex1 = toupper(line[2]) - '0';
4523 hex2 = toupper(line[3]) - '0';
4524 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4525 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4526 *line = (hex1<<4) + hex2;
4527 skip = 3;
4528 }
4529 else {
4530 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004531 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 }
4533 }
4534 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004535 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 end -= skip;
4537 }
4538 line++;
4539 }
4540 else if (*line == '#' || *line == '\n' || *line == '\r') {
4541 /* end of string, end of loop */
4542 *line = 0;
4543 break;
4544 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004545 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004546 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004547 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004548 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549 line++;
4550 args[++arg] = line;
4551 }
4552 else {
4553 line++;
4554 }
4555 }
4556
4557 /* empty line */
4558 if (!**args)
4559 continue;
4560
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004561 if (*line) {
4562 /* we had to stop due to too many args.
4563 * Let's terminate the string, print the offending part then cut the
4564 * last arg.
4565 */
4566 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4567 line++;
4568 *line = '\0';
4569
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004570 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004571 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 args[arg] = line;
4574 }
4575
Willy Tarreau540abe42007-05-02 20:50:16 +02004576 /* zero out remaining args and ensure that at least one entry
4577 * is zeroed out.
4578 */
4579 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 args[arg] = line;
4581 }
4582
Willy Tarreau3842f002009-06-14 11:39:52 +02004583 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004584 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004585 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004586 for (arg=0; *args[arg+1]; arg++)
4587 args[arg] = args[arg+1]; // shift args after inversion
4588 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004589 else if (!strcmp(args[0], "default")) {
4590 kwm = KWM_DEF;
4591 for (arg=0; *args[arg+1]; arg++)
4592 args[arg] = args[arg+1]; // shift args after inversion
4593 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004594
Willy Tarreau3842f002009-06-14 11:39:52 +02004595 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4596 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004597 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004598 }
4599
Willy Tarreau977b8e42006-12-29 14:19:17 +01004600 if (!strcmp(args[0], "listen") ||
4601 !strcmp(args[0], "frontend") ||
4602 !strcmp(args[0], "backend") ||
4603 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004604 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004606 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004607 cursection = strdup(args[0]);
4608 }
4609 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004611 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004612 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004613 } else if (!strcmp(args[0], "userlist")) {
4614 confsect = CFG_USERLIST;
4615 free(cursection);
4616 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 /* else it's a section keyword */
4619
4620 switch (confsect) {
4621 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004622 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 break;
4624 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004625 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004627 case CFG_USERLIST:
4628 err_code |= cfg_parse_users(file, linenum, args, kwm);
4629 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004631 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004634
4635 if (err_code & ERR_ABORT)
4636 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004638 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004639 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004641 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004642}
4643
Willy Tarreaubb925012009-07-23 13:36:36 +02004644/*
4645 * Returns the error code, 0 if OK, or any combination of :
4646 * - ERR_ABORT: must abort ASAP
4647 * - ERR_FATAL: we can continue parsing but not start the service
4648 * - ERR_WARN: a warning has been emitted
4649 * - ERR_ALERT: an alert has been emitted
4650 * Only the two first ones can stop processing, the two others are just
4651 * indicators.
4652 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004653int check_config_validity()
4654{
4655 int cfgerr = 0;
4656 struct proxy *curproxy = NULL;
4657 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004658 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004659 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004660 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661
4662 /*
4663 * Now, check for the integrity of all that we have collected.
4664 */
4665
4666 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004667 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004669 /* first, we will invert the proxy list order */
4670 curproxy = NULL;
4671 while (proxy) {
4672 struct proxy *next;
4673
4674 next = proxy->next;
4675 proxy->next = curproxy;
4676 curproxy = proxy;
4677 if (!next)
4678 break;
4679 proxy = next;
4680 }
4681
Willy Tarreaubaaee002006-06-26 02:48:02 +02004682 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004683 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004684 err_code |= ERR_ALERT | ERR_FATAL;
4685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 }
4687
4688 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004689 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004690 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004691 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004692 unsigned int next_id;
4693
4694 if (!curproxy->uuid) {
4695 /* proxy ID not set, use automatic numbering with first
4696 * spare entry starting with next_pxid.
4697 */
4698 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4699 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4700 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004701 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004702 next_pxid++;
4703
Willy Tarreau55ea7572007-06-17 19:56:27 +02004704
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004706 /* ensure we don't keep listeners uselessly bound */
4707 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 curproxy = curproxy->next;
4709 continue;
4710 }
4711
Willy Tarreauff01a212009-03-15 13:46:16 +01004712 switch (curproxy->mode) {
4713 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004714 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004715 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004716 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4717 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004718 cfgerr++;
4719 }
4720
4721 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004722 Warning("config : servers will be ignored for %s '%s'.\n",
4723 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004724 break;
4725
4726 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004727 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004728 break;
4729
4730 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004731 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004732 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004733 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4734 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004735 cfgerr++;
4736 }
4737 break;
4738 }
4739
4740 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004741 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4742 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 cfgerr++;
4744 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004745
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004746 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004747 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004748 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004749 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4750 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004751 cfgerr++;
4752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004754 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004755 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4756 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004757 cfgerr++;
4758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004760 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004761 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4762 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004763 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004764 }
4765 }
4766 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4767 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4768 /* If no LB algo is set in a backend, and we're not in
4769 * transparent mode, dispatch mode nor proxy mode, we
4770 * want to use balance roundrobin by default.
4771 */
4772 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4773 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 }
4775 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004776
Willy Tarreau82936582007-11-30 15:20:09 +01004777 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4778 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004779 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4780 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004781 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004782 }
4783
Willy Tarreauef781042010-01-27 11:53:01 +01004784 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4785 curproxy->options &= ~PR_O2_CHK_SNDST;
4786 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4787 "send-state", proxy_type_str(curproxy), curproxy->id);
4788 err_code |= ERR_WARN;
4789 }
4790
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004791 /* if a default backend was specified, let's find it */
4792 if (curproxy->defbe.name) {
4793 struct proxy *target;
4794
Alex Williams96532db2009-11-01 21:27:13 -05004795 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004796 if (!target) {
4797 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4798 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004799 cfgerr++;
4800 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004801 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4802 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004803 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004804 } else {
4805 free(curproxy->defbe.name);
4806 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004807 /* we force the backend to be present on at least all of
4808 * the frontend's processes.
4809 */
4810 target->bind_proc = curproxy->bind_proc ?
4811 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 }
4813 }
4814
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004815 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004816 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4817 /* map jump target for ACT_SETBE in req_rep chain */
4818 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004819 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004820 struct proxy *target;
4821
Willy Tarreaua496b602006-12-17 23:15:24 +01004822 if (exp->action != ACT_SETBE)
4823 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004824
Alex Williams96532db2009-11-01 21:27:13 -05004825 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004826 if (!target) {
4827 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4828 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004829 cfgerr++;
4830 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004831 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4832 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004833 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004834 } else {
4835 free((void *)exp->replace);
4836 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004837 /* we force the backend to be present on at least all of
4838 * the frontend's processes.
4839 */
4840 target->bind_proc = curproxy->bind_proc ?
4841 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004842 }
4843 }
4844 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004845
4846 /* find the target proxy for 'use_backend' rules */
4847 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004848 struct proxy *target;
4849
Alex Williams96532db2009-11-01 21:27:13 -05004850 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004851
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004852 if (!target) {
4853 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4854 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004855 cfgerr++;
4856 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004857 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4858 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004859 cfgerr++;
4860 } else {
4861 free((void *)rule->be.name);
4862 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004863 /* we force the backend to be present on at least all of
4864 * the frontend's processes.
4865 */
4866 target->bind_proc = curproxy->bind_proc ?
4867 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004868 }
4869 }
4870
Emeric Brunb982a3d2010-01-04 15:45:53 +01004871 /* find the target table for 'stick' rules */
4872 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4873 struct proxy *target;
4874
Emeric Brun1d33b292010-01-04 15:47:17 +01004875 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4876 if (mrule->flags & STK_IS_STORE)
4877 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4878
Emeric Brunb982a3d2010-01-04 15:45:53 +01004879 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02004880 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004881 else
4882 target = curproxy;
4883
4884 if (!target) {
4885 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4886 curproxy->id, mrule->table.name);
4887 cfgerr++;
4888 }
4889 else if (target->table.size == 0) {
4890 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4891 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4892 cfgerr++;
4893 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02004894 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004895 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4896 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4897 cfgerr++;
4898 }
4899 else {
4900 free((void *)mrule->table.name);
4901 mrule->table.t = &(target->table);
Willy Tarreau13c29de2010-06-06 16:40:39 +02004902 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004903 }
4904 }
4905
4906 /* find the target table for 'store response' rules */
4907 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4908 struct proxy *target;
4909
Emeric Brun1d33b292010-01-04 15:47:17 +01004910 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4911
Emeric Brunb982a3d2010-01-04 15:45:53 +01004912 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02004913 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004914 else
4915 target = curproxy;
4916
4917 if (!target) {
4918 Alert("Proxy '%s': unable to find store table '%s'.\n",
4919 curproxy->id, mrule->table.name);
4920 cfgerr++;
4921 }
4922 else if (target->table.size == 0) {
4923 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4924 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4925 cfgerr++;
4926 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02004927 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004928 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4929 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4930 cfgerr++;
4931 }
4932 else {
4933 free((void *)mrule->table.name);
4934 mrule->table.t = &(target->table);
Willy Tarreau13c29de2010-06-06 16:40:39 +02004935 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004936 }
4937 }
4938
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004939 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4940 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004941 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4942 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4943 "proxy", curproxy->id);
4944 cfgerr++;
4945 goto out_uri_auth_compat;
4946 }
4947
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004948 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004949 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004950 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004951 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004952
Willy Tarreau95fa4692010-02-01 13:05:50 +01004953 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4954 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004955
4956 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004957 uri_auth_compat_req[i++] = "realm";
4958 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4959 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004960
Willy Tarreau95fa4692010-02-01 13:05:50 +01004961 uri_auth_compat_req[i++] = "unless";
4962 uri_auth_compat_req[i++] = "{";
4963 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4964 uri_auth_compat_req[i++] = "}";
4965 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004966
Willy Tarreau95fa4692010-02-01 13:05:50 +01004967 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4968 if (!req_acl) {
4969 cfgerr++;
4970 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004971 }
4972
Willy Tarreau95fa4692010-02-01 13:05:50 +01004973 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4974
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004975 if (curproxy->uri_auth->auth_realm) {
4976 free(curproxy->uri_auth->auth_realm);
4977 curproxy->uri_auth->auth_realm = NULL;
4978 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004979
4980 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004981 }
4982out_uri_auth_compat:
4983
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004984 cfgerr += acl_find_targets(curproxy);
4985
Willy Tarreau2738a142006-07-08 17:28:09 +02004986 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004987 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004988 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004989 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004990 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004991 " | While not properly invalid, you will certainly encounter various problems\n"
4992 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004993 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004994 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004995 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004996 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004997
Willy Tarreau1fa31262007-12-03 00:36:16 +01004998 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4999 * We must still support older configurations, so let's find out whether those
5000 * parameters have been set or must be copied from contimeouts.
5001 */
5002 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005003 if (!curproxy->timeout.tarpit ||
5004 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005005 /* tarpit timeout not set. We search in the following order:
5006 * default.tarpit, curr.connect, default.connect.
5007 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005008 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005009 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005010 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005011 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005012 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005013 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005014 }
5015 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005016 (!curproxy->timeout.queue ||
5017 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005018 /* queue timeout not set. We search in the following order:
5019 * default.queue, curr.connect, default.connect.
5020 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005021 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005022 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005023 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005024 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005025 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005026 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005027 }
5028 }
5029
Willy Tarreau07a54902010-03-29 18:33:29 +02005030 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005031 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5032 curproxy->check_req = (char *)malloc(curproxy->check_len);
5033 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005034 }
5035
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005036 /* The small pools required for the capture lists */
5037 if (curproxy->nb_req_cap)
5038 curproxy->req_cap_pool = create_pool("ptrcap",
5039 curproxy->nb_req_cap * sizeof(char *),
5040 MEM_F_SHARED);
5041 if (curproxy->nb_rsp_cap)
5042 curproxy->rsp_cap_pool = create_pool("ptrcap",
5043 curproxy->nb_rsp_cap * sizeof(char *),
5044 MEM_F_SHARED);
5045
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005046 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5047 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5048 MEM_F_SHARED);
5049
Willy Tarreau86034312006-12-29 00:10:33 +01005050 /* for backwards compatibility with "listen" instances, if
5051 * fullconn is not set but maxconn is set, then maxconn
5052 * is used.
5053 */
5054 if (!curproxy->fullconn)
5055 curproxy->fullconn = curproxy->maxconn;
5056
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 /* first, we will invert the servers list order */
5058 newsrv = NULL;
5059 while (curproxy->srv) {
5060 struct server *next;
5061
5062 next = curproxy->srv->next;
5063 curproxy->srv->next = newsrv;
5064 newsrv = curproxy->srv;
5065 if (!next)
5066 break;
5067 curproxy->srv = next;
5068 }
5069
Willy Tarreaudd701652010-05-25 23:03:02 +02005070 /* assign automatic UIDs to servers which don't have one yet */
5071 next_id = 1;
5072 newsrv = curproxy->srv;
5073 while (newsrv != NULL) {
5074 if (!newsrv->puid) {
5075 /* server ID not set, use automatic numbering with first
5076 * spare entry starting with next_svid.
5077 */
5078 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5079 newsrv->conf.id.key = newsrv->puid = next_id;
5080 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5081 }
5082 next_id++;
5083 newsrv = newsrv->next;
5084 }
5085
Willy Tarreau20697042007-11-15 23:26:18 +01005086 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005087 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005089 /* We have to initialize the server lookup mechanism depending
5090 * on what LB algorithm was choosen.
5091 */
5092
5093 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5094 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5095 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005096 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5097 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5098 init_server_map(curproxy);
5099 } else {
5100 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5101 fwrr_init_server_groups(curproxy);
5102 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005103 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005104
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005105 case BE_LB_KIND_LC:
5106 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005107 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005108 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005109
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005110 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005111 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5112 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5113 chash_init_server_tree(curproxy);
5114 } else {
5115 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5116 init_server_map(curproxy);
5117 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005118 break;
5119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120
5121 if (curproxy->options & PR_O_LOGASAP)
5122 curproxy->to_log &= ~LW_BYTES;
5123
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005124 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5125 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5126 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5127 proxy_type_str(curproxy), curproxy->id);
5128 err_code |= ERR_WARN;
5129 }
5130
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005131 if (curproxy->mode != PR_MODE_HTTP) {
5132 int optnum;
5133
5134 if (curproxy->options & PR_O_COOK_ANY) {
5135 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5136 proxy_type_str(curproxy), curproxy->id);
5137 err_code |= ERR_WARN;
5138 }
5139
5140 if (curproxy->uri_auth) {
5141 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5142 proxy_type_str(curproxy), curproxy->id);
5143 err_code |= ERR_WARN;
5144 curproxy->uri_auth = NULL;
5145 }
5146
5147 if (curproxy->options & PR_O_FWDFOR) {
5148 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5149 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5150 err_code |= ERR_WARN;
5151 curproxy->options &= ~PR_O_FWDFOR;
5152 }
5153
5154 if (curproxy->options & PR_O_ORGTO) {
5155 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5156 "originalto", proxy_type_str(curproxy), curproxy->id);
5157 err_code |= ERR_WARN;
5158 curproxy->options &= ~PR_O_ORGTO;
5159 }
5160
5161 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5162 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5163 (curproxy->cap & cfg_opts[optnum].cap) &&
5164 (curproxy->options & cfg_opts[optnum].val)) {
5165 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5166 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5167 err_code |= ERR_WARN;
5168 curproxy->options &= ~cfg_opts[optnum].val;
5169 }
5170 }
5171
5172 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5173 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5174 (curproxy->cap & cfg_opts2[optnum].cap) &&
5175 (curproxy->options2 & cfg_opts2[optnum].val)) {
5176 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5177 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5178 err_code |= ERR_WARN;
5179 curproxy->options2 &= ~cfg_opts2[optnum].val;
5180 }
5181 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005182
Willy Tarreauefa5f512010-03-30 20:13:29 +02005183#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005184 if (curproxy->bind_hdr_occ) {
5185 curproxy->bind_hdr_occ = 0;
5186 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5187 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5188 err_code |= ERR_WARN;
5189 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005190#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005191 }
5192
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005194 * ensure that we're not cross-dressing a TCP server into HTTP.
5195 */
5196 newsrv = curproxy->srv;
5197 while (newsrv != NULL) {
5198 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005199 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5200 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005201 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005202 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005203
Willy Tarreauefa5f512010-03-30 20:13:29 +02005204#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005205 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5206 newsrv->bind_hdr_occ = 0;
5207 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5208 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5209 err_code |= ERR_WARN;
5210 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005211#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005212 newsrv = newsrv->next;
5213 }
5214
5215 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 * If this server supports a maxconn parameter, it needs a dedicated
5217 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005218 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 */
5220 newsrv = curproxy->srv;
5221 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005222 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 /* Only 'minconn' was specified, or it was higher than or equal
5224 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5225 * this will avoid further useless expensive computations.
5226 */
5227 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005228 } else if (newsrv->maxconn && !newsrv->minconn) {
5229 /* minconn was not specified, so we set it to maxconn */
5230 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005231 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005232 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5233 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005234 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
5236
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005237 if (newsrv->trackit) {
5238 struct proxy *px;
5239 struct server *srv;
5240 char *pname, *sname;
5241
5242 pname = newsrv->trackit;
5243 sname = strrchr(pname, '/');
5244
5245 if (sname)
5246 *sname++ = '\0';
5247 else {
5248 sname = pname;
5249 pname = NULL;
5250 }
5251
5252 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005253 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005254 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005255 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5256 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005257 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005258 cfgerr++;
5259 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005260 }
5261 } else
5262 px = curproxy;
5263
5264 srv = findserver(px, sname);
5265 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005266 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5267 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005268 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005269 cfgerr++;
5270 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005271 }
5272
5273 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005274 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005275 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005276 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005277 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005278 cfgerr++;
5279 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005280 }
5281
5282 if (curproxy != px &&
5283 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005284 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005285 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005286 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005287 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005288 cfgerr++;
5289 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005290 }
5291
5292 newsrv->tracked = srv;
5293 newsrv->tracknext = srv->tracknext;
5294 srv->tracknext = newsrv;
5295
5296 free(newsrv->trackit);
5297 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005298 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 newsrv = newsrv->next;
5300 }
5301
Willy Tarreauc1a21672009-08-16 22:37:44 +02005302 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005303 curproxy->accept = frontend_accept;
5304
Willy Tarreauc1a21672009-08-16 22:37:44 +02005305 if (curproxy->tcp_req.inspect_delay ||
5306 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02005307 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005308
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005309 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005310 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005311 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005312 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005313
5314 /* both TCP and HTTP must check switching rules */
5315 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5316 }
5317
5318 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02005319 if (curproxy->tcp_req.inspect_delay ||
5320 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5321 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
5322
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005323 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005324 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005325 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005326 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005327
5328 /* If the backend does requires RDP cookie persistence, we have to
5329 * enable the corresponding analyser.
5330 */
5331 if (curproxy->options2 & PR_O2_RDPC_PRST)
5332 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5333 }
5334
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005335 listener = NULL;
5336 while (curproxy->listen) {
5337 struct listener *next;
5338
5339 next = curproxy->listen->next;
5340 curproxy->listen->next = listener;
5341 listener = curproxy->listen;
5342
5343 if (!next)
5344 break;
5345
5346 curproxy->listen = next;
5347 }
5348
Willy Tarreaue6b98942007-10-29 01:09:36 +01005349 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005350 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005351 listener = curproxy->listen;
5352 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005353 if (!listener->luid) {
5354 /* listener ID not set, use automatic numbering with first
5355 * spare entry starting with next_luid.
5356 */
5357 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5358 listener->conf.id.key = listener->luid = next_id;
5359 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005360 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005361 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005362
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005363 /* enable separate counters */
5364 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5365 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5366 if (!listener->name) {
5367 sprintf(trash, "sock-%d", listener->luid);
5368 listener->name = strdup(trash);
5369 }
5370 }
5371
Willy Tarreaue6b98942007-10-29 01:09:36 +01005372 if (curproxy->options & PR_O_TCP_NOLING)
5373 listener->options |= LI_O_NOLINGER;
5374 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005375 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005376 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005377 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02005378 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005379 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005380 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005381
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02005382 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
5383 listener->options |= LI_O_TCP_RULES;
5384
Willy Tarreaude3041d2010-05-31 10:56:17 +02005385 if (curproxy->mon_mask.s_addr)
5386 listener->options |= LI_O_CHK_MONNET;
5387
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005388 /* smart accept mode is automatic in HTTP mode */
5389 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5390 (curproxy->mode == PR_MODE_HTTP &&
5391 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5392 listener->options |= LI_O_NOQUICKACK;
5393
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005394 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005395 listener = listener->next;
5396 }
5397
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 curproxy = curproxy->next;
5399 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005400
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005401 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5402 struct auth_users *curuser;
5403 int g;
5404
5405 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5406 unsigned int group_mask = 0;
5407 char *group = NULL;
5408
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005409 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005410 continue;
5411
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005412 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005413
5414 for (g = 0; g < curuserlist->grpcnt; g++)
5415 if (!strcmp(curuserlist->groups[g], group))
5416 break;
5417
5418 if (g == curuserlist->grpcnt) {
5419 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5420 curuserlist->name, group, curuser->user);
5421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
5423 }
5424
5425 group_mask |= (1 << g);
5426 }
5427
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005428 free(curuser->u.groups);
5429 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005430 }
5431
5432 for (g = 0; g < curuserlist->grpcnt; g++) {
5433 char *user = NULL;
5434
5435 if (!curuserlist->groupusers[g])
5436 continue;
5437
5438 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5439 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5440 if (!strcmp(curuser->user, user))
5441 break;
5442
5443 if (!curuser) {
5444 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5445 curuserlist->name, user, curuserlist->groups[g]);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
5449
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005450 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005451 }
5452
5453 free(curuserlist->groupusers[g]);
5454 }
5455
5456 free(curuserlist->groupusers);
5457
5458#ifdef DEBUG_AUTH
5459 for (g = 0; g < curuserlist->grpcnt; g++) {
5460 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5461
5462 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5463 if (curuser->group_mask & (1 << g))
5464 fprintf(stderr, " %s", curuser->user);
5465 }
5466
5467 fprintf(stderr, "\n");
5468 }
5469#endif
5470
5471 }
5472
Willy Tarreau056f5682010-06-06 15:51:11 +02005473 /* initialize stick-tables on backend capable proxies. This must not
5474 * be done earlier because the data size may be discovered while parsing
5475 * other proxies.
5476 */
5477 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005478 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02005479
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005480 /*
5481 * Recount currently required checks.
5482 */
5483
5484 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5485 int optnum;
5486
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005487 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5488 if (curproxy->options & cfg_opts[optnum].val)
5489 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005490
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005491 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5492 if (curproxy->options2 & cfg_opts2[optnum].val)
5493 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005494 }
5495
Willy Tarreaubb925012009-07-23 13:36:36 +02005496 if (cfgerr > 0)
5497 err_code |= ERR_ALERT | ERR_FATAL;
5498 out:
5499 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500}
5501
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005502/*
5503 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5504 * parsing sessions.
5505 */
5506void cfg_register_keywords(struct cfg_kw_list *kwl)
5507{
5508 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5509}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005511/*
5512 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5513 */
5514void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5515{
5516 LIST_DEL(&kwl->list);
5517 LIST_INIT(&kwl->list);
5518}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519
5520/*
5521 * Local variables:
5522 * c-indent-level: 8
5523 * c-basic-offset: 8
5524 * End:
5525 */