blob: 6ca7ec57a4f09a711d756f6ca75e431dcebb1371 [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) {
Willy Tarreauac782882010-06-20 10:41:54 +02002278 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002279 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002280
2281 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002282 nw = args[myidx];
2283 while (*nw) {
2284 /* the "store" keyword supports a comma-separated list */
2285 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002286 sa = NULL; /* store arg */
2287 while (*nw && *nw != ',') {
2288 if (*nw == '(') {
2289 *nw = 0;
2290 sa = ++nw;
2291 while (*nw != ')') {
2292 if (!*nw) {
2293 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2294 file, linenum, args[0], cw);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298 nw++;
2299 }
2300 *nw = '\0';
2301 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002302 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002303 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002304 if (*nw)
2305 *nw++ = '\0';
2306 type = stktable_get_data_type(cw);
2307 if (type < 0) {
2308 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2309 file, linenum, args[0], cw);
2310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
2312 }
Willy Tarreauac782882010-06-20 10:41:54 +02002313
2314 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2315 switch (err) {
2316 case PE_NONE: break;
2317 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002318 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2319 file, linenum, args[0], cw);
2320 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002321 break;
2322
2323 case PE_ARG_MISSING:
2324 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2325 file, linenum, args[0], cw);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328
2329 case PE_ARG_NOT_USED:
2330 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2331 file, linenum, args[0], cw);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334
2335 default:
2336 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2337 file, linenum, args[0], cw);
2338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002340 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002341 }
2342 myidx++;
2343 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002344 else {
2345 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2346 file, linenum, args[myidx]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002349 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002350 }
2351
2352 if (!curproxy->table.size) {
2353 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2354 file, linenum);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
2358
2359 if (curproxy->table.type == (unsigned int)-1) {
2360 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2361 file, linenum);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365 }
2366 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002367 struct sticking_rule *rule;
2368 struct pattern_expr *expr;
2369 int myidx = 0;
2370 const char *name = NULL;
2371 int flags;
2372
2373 if (curproxy == &defproxy) {
2374 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
2379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2380 err_code |= ERR_WARN;
2381 goto out;
2382 }
2383
2384 myidx++;
2385 if ((strcmp(args[myidx], "store") == 0) ||
2386 (strcmp(args[myidx], "store-request") == 0)) {
2387 myidx++;
2388 flags = STK_IS_STORE;
2389 }
2390 else if (strcmp(args[myidx], "store-response") == 0) {
2391 myidx++;
2392 flags = STK_IS_STORE | STK_ON_RSP;
2393 }
2394 else if (strcmp(args[myidx], "match") == 0) {
2395 myidx++;
2396 flags = STK_IS_MATCH;
2397 }
2398 else if (strcmp(args[myidx], "on") == 0) {
2399 myidx++;
2400 flags = STK_IS_MATCH | STK_IS_STORE;
2401 }
2402 else {
2403 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
2406 }
2407
2408 if (*(args[myidx]) == 0) {
2409 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
2412 }
2413
2414 expr = pattern_parse_expr(args, &myidx);
2415 if (!expr) {
2416 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
2419 }
2420
2421 if (flags & STK_ON_RSP) {
2422 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2423 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2424 file, linenum, args[0], expr->fetch->kw);
2425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
2427 }
2428 } else {
2429 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2430 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2431 file, linenum, args[0], expr->fetch->kw);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435 }
2436
2437 if (strcmp(args[myidx], "table") == 0) {
2438 myidx++;
2439 name = args[myidx++];
2440 }
2441
Willy Tarreauef6494c2010-01-28 17:12:36 +01002442 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2443 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002444 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2445 file, linenum, args[0]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002449 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002450 else if (*(args[myidx])) {
2451 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2452 file, linenum, args[0], args[myidx]);
2453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
2455 }
2456
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002457 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2458
Emeric Brunb982a3d2010-01-04 15:45:53 +01002459 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2460 rule->cond = cond;
2461 rule->expr = expr;
2462 rule->flags = flags;
2463 rule->table.name = name ? strdup(name) : NULL;
2464 LIST_INIT(&rule->list);
2465 if (flags & STK_ON_RSP)
2466 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2467 else
2468 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002473
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2475 curproxy->uri_auth = NULL; /* we must detach from the default config */
2476
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002477 if (!*args[1]) {
2478 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 } else if (!strcmp(args[1], "uri")) {
2480 if (*(args[2]) == 0) {
2481 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2485 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002486 err_code |= ERR_ALERT | ERR_ABORT;
2487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 }
2489 } else if (!strcmp(args[1], "realm")) {
2490 if (*(args[2]) == 0) {
2491 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2495 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_ABORT;
2497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002499 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002500 unsigned interval;
2501
2502 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2503 if (err) {
2504 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2505 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002508 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2509 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_ABORT;
2511 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002512 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002513 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2514 struct req_acl_rule *req_acl;
2515
2516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
2522 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2523 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2524 err_code |= ERR_ALERT | ERR_ABORT;
2525 goto out;
2526 }
2527
2528 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2529 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2530 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2531 file, linenum, args[0]);
2532 err_code |= ERR_WARN;
2533 }
2534
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002535 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002536
2537 if (!req_acl) {
2538 err_code |= ERR_ALERT | ERR_ABORT;
2539 goto out;
2540 }
2541
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002542 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002543 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2544
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 } else if (!strcmp(args[1], "auth")) {
2546 if (*(args[2]) == 0) {
2547 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2551 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_ABORT;
2553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 }
2555 } else if (!strcmp(args[1], "scope")) {
2556 if (*(args[2]) == 0) {
2557 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2561 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_ABORT;
2563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565 } else if (!strcmp(args[1], "enable")) {
2566 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2567 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_ABORT;
2569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002571 } else if (!strcmp(args[1], "hide-version")) {
2572 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2573 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_ABORT;
2575 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002576 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002577 } else if (!strcmp(args[1], "show-legends")) {
2578 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2579 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2580 err_code |= ERR_ALERT | ERR_ABORT;
2581 goto out;
2582 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002583 } else if (!strcmp(args[1], "show-node")) {
2584
2585 if (*args[2]) {
2586 int i;
2587 char c;
2588
2589 for (i=0; args[2][i]; i++) {
2590 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002591 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2592 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002593 break;
2594 }
2595
2596 if (!i || args[2][i]) {
2597 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2598 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2599 file, linenum, args[0], args[1]);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
2603 }
2604
2605 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2606 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2607 err_code |= ERR_ALERT | ERR_ABORT;
2608 goto out;
2609 }
2610 } else if (!strcmp(args[1], "show-desc")) {
2611 char *desc = NULL;
2612
2613 if (*args[2]) {
2614 int i, len=0;
2615 char *d;
2616
2617 for(i=2; *args[i]; i++)
2618 len += strlen(args[i])+1;
2619
2620 desc = d = (char *)calloc(1, len);
2621
2622 d += sprintf(d, "%s", args[2]);
2623 for(i=3; *args[i]; i++)
2624 d += sprintf(d, " %s", args[i]);
2625 }
2626
2627 if (!*args[2] && !global.desc)
2628 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2629 file, linenum, args[1]);
2630 else {
2631 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2632 free(desc);
2633 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2634 err_code |= ERR_ALERT | ERR_ABORT;
2635 goto out;
2636 }
2637 free(desc);
2638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002640stats_error_parsing:
2641 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2642 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }
2646 }
2647 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002648 int optnum;
2649
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002650 if (*(args[1]) == '\0') {
2651 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002656
2657 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2658 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002659 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2660 err_code |= ERR_WARN;
2661 goto out;
2662 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002663
Willy Tarreau3842f002009-06-14 11:39:52 +02002664 curproxy->no_options &= ~cfg_opts[optnum].val;
2665 curproxy->options &= ~cfg_opts[optnum].val;
2666
2667 switch (kwm) {
2668 case KWM_STD:
2669 curproxy->options |= cfg_opts[optnum].val;
2670 break;
2671 case KWM_NO:
2672 curproxy->no_options |= cfg_opts[optnum].val;
2673 break;
2674 case KWM_DEF: /* already cleared */
2675 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002676 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002677
Willy Tarreau93893792009-07-23 13:19:11 +02002678 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002679 }
2680 }
2681
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002682 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2683 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002684 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2685 err_code |= ERR_WARN;
2686 goto out;
2687 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002688
Willy Tarreau3842f002009-06-14 11:39:52 +02002689 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2690 curproxy->options2 &= ~cfg_opts2[optnum].val;
2691
2692 switch (kwm) {
2693 case KWM_STD:
2694 curproxy->options2 |= cfg_opts2[optnum].val;
2695 break;
2696 case KWM_NO:
2697 curproxy->no_options2 |= cfg_opts2[optnum].val;
2698 break;
2699 case KWM_DEF: /* already cleared */
2700 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002701 }
Willy Tarreau93893792009-07-23 13:19:11 +02002702 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002703 }
2704 }
2705
Willy Tarreau3842f002009-06-14 11:39:52 +02002706 if (kwm != KWM_STD) {
2707 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002708 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002711 }
2712
Emeric Brun3a058f32009-06-30 18:26:00 +02002713 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002715 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002717 if (*(args[2]) != '\0') {
2718 if (!strcmp(args[2], "clf")) {
2719 curproxy->options2 |= PR_O2_CLFLOG;
2720 } else {
2721 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002724 }
2725 }
2726 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 else if (!strcmp(args[1], "tcplog"))
2728 /* generate a detailed TCP log */
2729 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 else if (!strcmp(args[1], "tcpka")) {
2731 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002732 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002734
2735 if (curproxy->cap & PR_CAP_FE)
2736 curproxy->options |= PR_O_TCP_CLI_KA;
2737 if (curproxy->cap & PR_CAP_BE)
2738 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 }
2740 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_WARN;
2743
Willy Tarreaubaaee002006-06-26 02:48:02 +02002744 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002745 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002746 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002747 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002748 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002749 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002750 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 if (!*args[2]) { /* no argument */
2752 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2753 curproxy->check_len = strlen(DEF_CHECK_REQ);
2754 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002755 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->check_req = (char *)malloc(reqlen);
2757 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002758 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002760 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 if (*args[4])
2762 reqlen += strlen(args[4]);
2763 else
2764 reqlen += strlen("HTTP/1.0");
2765
2766 curproxy->check_req = (char *)malloc(reqlen);
2767 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002768 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002770 }
2771 else if (!strcmp(args[1], "ssl-hello-chk")) {
2772 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002773 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002775
Willy Tarreaua534fea2008-08-03 12:19:50 +02002776 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002777 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002778 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002779 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002780 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002781 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
Willy Tarreau23677902007-05-08 23:50:35 +02002783 else if (!strcmp(args[1], "smtpchk")) {
2784 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002785 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002786 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002787 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002788 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002789 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002790 curproxy->options |= PR_O_SMTP_CHK;
2791
2792 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2793 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2794 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2795 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2796 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2797 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2798 curproxy->check_req = (char *)malloc(reqlen);
2799 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2800 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2801 } else {
2802 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2803 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2804 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2805 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2806 }
2807 }
2808 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002809 else if (!strcmp(args[1], "mysql-check")) {
2810 /* use MYSQL request to check servers' health */
2811 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002812 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002813 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002814 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002815 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002816 curproxy->options2 |= PR_O2_MYSQL_CHK;
2817 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002818 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002819 int cur_arg;
2820
2821 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2822 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002823 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002824
2825 curproxy->options |= PR_O_FWDFOR;
2826
2827 free(curproxy->fwdfor_hdr_name);
2828 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2829 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2830
2831 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2832 cur_arg = 2;
2833 while (*(args[cur_arg])) {
2834 if (!strcmp(args[cur_arg], "except")) {
2835 /* suboption except - needs additional argument for it */
2836 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2837 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2838 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002841 }
2842 /* flush useless bits */
2843 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002844 cur_arg += 2;
2845 } else if (!strcmp(args[cur_arg], "header")) {
2846 /* suboption header - needs additional argument for it */
2847 if (*(args[cur_arg+1]) == 0) {
2848 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2849 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002852 }
2853 free(curproxy->fwdfor_hdr_name);
2854 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2855 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2856 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002857 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002858 /* unknown suboption - catchall */
2859 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2860 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002863 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002864 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002865 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002866 else if (!strcmp(args[1], "originalto")) {
2867 int cur_arg;
2868
2869 /* insert x-original-to field, but not for the IP address listed as an except.
2870 * set default options (ie: bitfield, header name, etc)
2871 */
2872
2873 curproxy->options |= PR_O_ORGTO;
2874
2875 free(curproxy->orgto_hdr_name);
2876 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2877 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2878
2879 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2880 cur_arg = 2;
2881 while (*(args[cur_arg])) {
2882 if (!strcmp(args[cur_arg], "except")) {
2883 /* suboption except - needs additional argument for it */
2884 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2885 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2886 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002889 }
2890 /* flush useless bits */
2891 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2892 cur_arg += 2;
2893 } else if (!strcmp(args[cur_arg], "header")) {
2894 /* suboption header - needs additional argument for it */
2895 if (*(args[cur_arg+1]) == 0) {
2896 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2897 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002900 }
2901 free(curproxy->orgto_hdr_name);
2902 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2903 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2904 cur_arg += 2;
2905 } else {
2906 /* unknown suboption - catchall */
2907 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2908 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002911 }
2912 } /* end while loop */
2913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 else {
2915 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
Willy Tarreau93893792009-07-23 13:19:11 +02002919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002921 else if (!strcmp(args[0], "default_backend")) {
2922 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002924
2925 if (*(args[1]) == 0) {
2926 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002929 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002930 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002931 curproxy->defbe.name = strdup(args[1]);
2932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002936
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002937 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 /* enable reconnections to dispatch */
2941 curproxy->options |= PR_O_REDISP;
2942 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002943 else if (!strcmp(args[0], "http-check")) {
2944 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002945 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002946
2947 if (strcmp(args[1], "disable-on-404") == 0) {
2948 /* enable a graceful server shutdown on an HTTP 404 response */
2949 curproxy->options |= PR_O_DISABLE404;
2950 }
Willy Tarreauef781042010-01-27 11:53:01 +01002951 else if (strcmp(args[1], "send-state") == 0) {
2952 /* enable emission of the apparent state of a server in HTTP checks */
2953 curproxy->options2 |= PR_O2_CHK_SNDST;
2954 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002955 else {
2956 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002957 err_code |= ERR_ALERT | ERR_FATAL;
2958 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002959 }
2960 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002961 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002962 if (curproxy == &defproxy) {
2963 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002966 }
2967
Willy Tarreaub80c2302007-11-30 20:51:32 +01002968 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002970
2971 if (strcmp(args[1], "fail") == 0) {
2972 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002973 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002974 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2975 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002978 }
2979
Willy Tarreauef6494c2010-01-28 17:12:36 +01002980 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002981 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2982 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002985 }
2986 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2987 }
2988 else {
2989 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002992 }
2993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994#ifdef TPROXY
2995 else if (!strcmp(args[0], "transparent")) {
2996 /* enable transparent proxy connections */
2997 curproxy->options |= PR_O_TRANSP;
2998 }
2999#endif
3000 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003001 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003003
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 if (*(args[1]) == 0) {
3005 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 }
3009 curproxy->maxconn = atol(args[1]);
3010 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003011 else if (!strcmp(args[0], "backlog")) { /* backlog */
3012 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003014
3015 if (*(args[1]) == 0) {
3016 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003019 }
3020 curproxy->backlog = atol(args[1]);
3021 }
Willy Tarreau86034312006-12-29 00:10:33 +01003022 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025
Willy Tarreau86034312006-12-29 00:10:33 +01003026 if (*(args[1]) == 0) {
3027 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003030 }
3031 curproxy->fullconn = atol(args[1]);
3032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3034 if (*(args[1]) == 0) {
3035 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003039 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3040 if (err) {
3041 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3042 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003045 }
3046 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 }
3048 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003049 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 if (curproxy == &defproxy) {
3051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 if (strchr(args[1], ':') == NULL) {
3059 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003063 sk = str2sa(args[1]);
3064 if (!sk) {
3065 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
3068 }
3069 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 }
3071 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003072 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003074
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003075 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003076 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3077 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003082 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3083 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3084 err_code |= ERR_WARN;
3085
3086 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3087 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3088 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3089 }
3090 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3091 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3092 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3093 }
3094 else {
3095 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
3099 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003100 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003102 char *rport, *raddr;
3103 short realport = 0;
3104 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003106 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003111 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113
3114 if (!*args[2]) {
3115 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3116 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003120
3121 err = invalid_char(args[1]);
3122 if (err) {
3123 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3124 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003127 }
3128
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003129 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003130 struct sockaddr_in *sk;
3131
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003132 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3133 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3134 err_code |= ERR_ALERT | ERR_ABORT;
3135 goto out;
3136 }
3137
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003138 /* the servers are linked backwards first */
3139 newsrv->next = curproxy->srv;
3140 curproxy->srv = newsrv;
3141 newsrv->proxy = curproxy;
3142 newsrv->conf.file = file;
3143 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003145 LIST_INIT(&newsrv->pendconns);
3146 do_check = 0;
3147 newsrv->state = SRV_RUNNING; /* early server setup */
3148 newsrv->last_change = now.tv_sec;
3149 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003151 /* several ways to check the port component :
3152 * - IP => port=+0, relative
3153 * - IP: => port=+0, relative
3154 * - IP:N => port=N, absolute
3155 * - IP:+N => port=+N, relative
3156 * - IP:-N => port=-N, relative
3157 */
3158 raddr = strdup(args[2]);
3159 rport = strchr(raddr, ':');
3160 if (rport) {
3161 *rport++ = 0;
3162 realport = atol(rport);
3163 if (!isdigit((unsigned char)*rport))
3164 newsrv->state |= SRV_MAPPORTS;
3165 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003167
Willy Tarreaud5191e72010-02-09 20:50:45 +01003168 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003169 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003170 if (!sk) {
3171 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
3175 newsrv->addr = *sk;
3176 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003177
3178 newsrv->check_port = curproxy->defsrv.check_port;
3179 newsrv->inter = curproxy->defsrv.inter;
3180 newsrv->fastinter = curproxy->defsrv.fastinter;
3181 newsrv->downinter = curproxy->defsrv.downinter;
3182 newsrv->rise = curproxy->defsrv.rise;
3183 newsrv->fall = curproxy->defsrv.fall;
3184 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3185 newsrv->minconn = curproxy->defsrv.minconn;
3186 newsrv->maxconn = curproxy->defsrv.maxconn;
3187 newsrv->slowstart = curproxy->defsrv.slowstart;
3188 newsrv->onerror = curproxy->defsrv.onerror;
3189 newsrv->consecutive_errors_limit
3190 = curproxy->defsrv.consecutive_errors_limit;
3191 newsrv->uweight = newsrv->iweight
3192 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003194 newsrv->curfd = -1; /* no health-check in progress */
3195 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003197 cur_arg = 3;
3198 } else {
3199 newsrv = &curproxy->defsrv;
3200 cur_arg = 1;
3201 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003202
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003204 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003205 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003206
3207 if (!*args[cur_arg + 1]) {
3208 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3209 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003212 }
3213
3214 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003215 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003216
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003217 if (newsrv->puid <= 0) {
3218 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003219 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003222 }
3223
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003224 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3225 if (node) {
3226 struct server *target = container_of(node, struct server, conf.id);
3227 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3228 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3229 err_code |= ERR_ALERT | ERR_FATAL;
3230 goto out;
3231 }
3232 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003233 cur_arg += 2;
3234 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003235 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 newsrv->cookie = strdup(args[cur_arg + 1]);
3237 newsrv->cklen = strlen(args[cur_arg + 1]);
3238 cur_arg += 2;
3239 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003240 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003241 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3242 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3243 cur_arg += 2;
3244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003246 if (!*args[cur_arg + 1]) {
3247 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3248 file, linenum, args[cur_arg]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003254 if (newsrv->rise <= 0) {
3255 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3256 file, linenum, args[cur_arg]);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260
Willy Tarreau96839092010-03-29 10:02:24 +02003261 if (newsrv->health)
3262 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 cur_arg += 2;
3264 }
3265 else if (!strcmp(args[cur_arg], "fall")) {
3266 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003267
3268 if (!*args[cur_arg + 1]) {
3269 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3270 file, linenum, args[cur_arg]);
3271 err_code |= ERR_ALERT | ERR_FATAL;
3272 goto out;
3273 }
3274
3275 if (newsrv->fall <= 0) {
3276 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3277 file, linenum, args[cur_arg]);
3278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
3280 }
3281
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 cur_arg += 2;
3283 }
3284 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003285 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3286 if (err) {
3287 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3288 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003291 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003292 if (val <= 0) {
3293 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3294 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003297 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003298 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 cur_arg += 2;
3300 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003301 else if (!strcmp(args[cur_arg], "fastinter")) {
3302 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3303 if (err) {
3304 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3305 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003308 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003309 if (val <= 0) {
3310 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3311 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003314 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003315 newsrv->fastinter = val;
3316 cur_arg += 2;
3317 }
3318 else if (!strcmp(args[cur_arg], "downinter")) {
3319 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3320 if (err) {
3321 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3322 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003325 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003326 if (val <= 0) {
3327 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3328 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003331 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003332 newsrv->downinter = val;
3333 cur_arg += 2;
3334 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003335 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003336 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3337 if (!sk) {
3338 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
3341 }
3342 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003343 cur_arg += 2;
3344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 else if (!strcmp(args[cur_arg], "port")) {
3346 newsrv->check_port = atol(args[cur_arg + 1]);
3347 cur_arg += 2;
3348 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003349 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 newsrv->state |= SRV_BACKUP;
3351 cur_arg ++;
3352 }
3353 else if (!strcmp(args[cur_arg], "weight")) {
3354 int w;
3355 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003356 if (w < 0 || w > 256) {
3357 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003362 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 cur_arg += 2;
3364 }
3365 else if (!strcmp(args[cur_arg], "minconn")) {
3366 newsrv->minconn = atol(args[cur_arg + 1]);
3367 cur_arg += 2;
3368 }
3369 else if (!strcmp(args[cur_arg], "maxconn")) {
3370 newsrv->maxconn = atol(args[cur_arg + 1]);
3371 cur_arg += 2;
3372 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003373 else if (!strcmp(args[cur_arg], "maxqueue")) {
3374 newsrv->maxqueue = atol(args[cur_arg + 1]);
3375 cur_arg += 2;
3376 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003377 else if (!strcmp(args[cur_arg], "slowstart")) {
3378 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003379 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003380 if (err) {
3381 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3382 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003385 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003386 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003387 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3388 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003391 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003392 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003393 cur_arg += 2;
3394 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003395 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003396
3397 if (!*args[cur_arg + 1]) {
3398 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3399 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003402 }
3403
3404 newsrv->trackit = strdup(args[cur_arg + 1]);
3405
3406 cur_arg += 2;
3407 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003408 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 global.maxsock++;
3410 do_check = 1;
3411 cur_arg += 1;
3412 }
Willy Tarreau96839092010-03-29 10:02:24 +02003413 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3414 newsrv->state |= SRV_MAINTAIN;
3415 newsrv->state &= ~SRV_RUNNING;
3416 newsrv->health = 0;
3417 cur_arg += 1;
3418 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003419 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003420 if (!strcmp(args[cur_arg + 1], "none"))
3421 newsrv->observe = HANA_OBS_NONE;
3422 else if (!strcmp(args[cur_arg + 1], "layer4"))
3423 newsrv->observe = HANA_OBS_LAYER4;
3424 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3425 if (curproxy->mode != PR_MODE_HTTP) {
3426 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3427 file, linenum, args[cur_arg + 1]);
3428 err_code |= ERR_ALERT;
3429 }
3430 newsrv->observe = HANA_OBS_LAYER7;
3431 }
3432 else {
3433 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3434 "'l4events', 'http-responses' but get '%s'\n",
3435 file, linenum, args[cur_arg], args[cur_arg + 1]);
3436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
3438 }
3439
3440 cur_arg += 2;
3441 }
3442 else if (!strcmp(args[cur_arg], "on-error")) {
3443 if (!strcmp(args[cur_arg + 1], "fastinter"))
3444 newsrv->onerror = HANA_ONERR_FASTINTER;
3445 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3446 newsrv->onerror = HANA_ONERR_FAILCHK;
3447 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3448 newsrv->onerror = HANA_ONERR_SUDDTH;
3449 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3450 newsrv->onerror = HANA_ONERR_MARKDWN;
3451 else {
3452 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3453 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3454 file, linenum, args[cur_arg], args[cur_arg + 1]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
3458
3459 cur_arg += 2;
3460 }
3461 else if (!strcmp(args[cur_arg], "error-limit")) {
3462 if (!*args[cur_arg + 1]) {
3463 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3464 file, linenum, args[cur_arg]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468
3469 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3470
3471 if (newsrv->consecutive_errors_limit <= 0) {
3472 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3473 file, linenum, args[cur_arg]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003477 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003478 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003479 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003480 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003481 struct sockaddr_in *sk;
3482
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003484#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003485 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003486 file, linenum, "source", "usesrc");
3487#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003488 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003490#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 }
3494 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003495 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3496 if (!sk) {
3497 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003502
3503 if (port_low != port_high) {
3504 int i;
3505 if (port_low <= 0 || port_low > 65535 ||
3506 port_high <= 0 || port_high > 65535 ||
3507 port_low > port_high) {
3508 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3509 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003512 }
3513 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3514 for (i = 0; i < newsrv->sport_range->size; i++)
3515 newsrv->sport_range->ports[i] = port_low + i;
3516 }
3517
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003519 while (*(args[cur_arg])) {
3520 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003521#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3522#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003523 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3524 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3525 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003528 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003529#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003530 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003531 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01003532 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003535 }
3536 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003537 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003538 newsrv->state |= SRV_TPROXY_CLI;
3539 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003540 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003541 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003542 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3543 char *name, *end;
3544
3545 name = args[cur_arg+1] + 7;
3546 while (isspace(*name))
3547 name++;
3548
3549 end = name;
3550 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3551 end++;
3552
3553 newsrv->state &= ~SRV_TPROXY_MASK;
3554 newsrv->state |= SRV_TPROXY_DYN;
3555 newsrv->bind_hdr_name = calloc(1, end - name + 1);
3556 newsrv->bind_hdr_len = end - name;
3557 memcpy(newsrv->bind_hdr_name, name, end - name);
3558 newsrv->bind_hdr_name[end-name] = '\0';
3559 newsrv->bind_hdr_occ = -1;
3560
3561 /* now look for an occurrence number */
3562 while (isspace(*end))
3563 end++;
3564 if (*end == ',') {
3565 end++;
3566 name = end;
3567 if (*end == '-')
3568 end++;
3569 while (isdigit(*end))
3570 end++;
3571 newsrv->bind_hdr_occ = strl2ic(name, end-name);
3572 }
3573
3574 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
3575 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3576 " occurrences values smaller than %d.\n",
3577 file, linenum, MAX_HDR_HISTORY);
3578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
3580 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01003581 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003582 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3583 if (!sk) {
3584 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
3587 }
3588 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003589 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003590 }
3591 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003592#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003593 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003594#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003595 cur_arg += 2;
3596 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003597#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003598 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003599 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003602#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3603 } /* "usesrc" */
3604
3605 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3606#ifdef SO_BINDTODEVICE
3607 if (!*args[cur_arg + 1]) {
3608 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003612 }
3613 if (newsrv->iface_name)
3614 free(newsrv->iface_name);
3615
3616 newsrv->iface_name = strdup(args[cur_arg + 1]);
3617 newsrv->iface_len = strlen(newsrv->iface_name);
3618 global.last_checks |= LSTCHK_NETADM;
3619#else
3620 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3621 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003624#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003625 cur_arg += 2;
3626 continue;
3627 }
3628 /* this keyword in not an option of "source" */
3629 break;
3630 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003632 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003633 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3634 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003639 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003640 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 +01003641 file, linenum, newsrv->id);
3642 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003643 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 +01003644 file, linenum);
3645
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003648 }
3649 }
3650
3651 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003652 if (newsrv->trackit) {
3653 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3654 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003657 }
3658
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003659 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3660 newsrv->check_port = newsrv->check_addr.sin_port;
3661
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3663 newsrv->check_port = realport; /* by default */
3664 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003665 /* not yet valid, because no port was set on
3666 * the server either. We'll check if we have
3667 * a known port on the first listener.
3668 */
3669 struct listener *l;
3670 l = curproxy->listen;
3671 if (l) {
3672 int port;
3673 port = (l->addr.ss_family == AF_INET6)
3674 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3675 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3676 newsrv->check_port = port;
3677 }
3678 }
3679 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003680 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3681 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003685
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003686 /* Allocate buffer for partial check results... */
3687 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3688 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3689 err_code |= ERR_ALERT | ERR_ABORT;
3690 goto out;
3691 }
3692
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003693 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 newsrv->state |= SRV_CHECKED;
3695 }
3696
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003697 if (!defsrv) {
3698 if (newsrv->state & SRV_BACKUP)
3699 curproxy->srv_bck++;
3700 else
3701 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003702
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003703 newsrv->prev_state = newsrv->state;
3704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
3706 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003707 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 int facility;
3709
3710 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3711 curproxy->logfac1 = global.logfac1;
3712 curproxy->logsrv1 = global.logsrv1;
3713 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003714 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 curproxy->logfac2 = global.logfac2;
3716 curproxy->logsrv2 = global.logsrv2;
3717 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003718 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
3720 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003721 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722
3723 facility = get_log_facility(args[2]);
3724 if (facility < 0) {
3725 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3726 exit(1);
3727 }
3728
3729 level = 7; /* max syslog level = debug */
3730 if (*(args[3])) {
3731 level = get_log_level(args[3]);
3732 if (level < 0) {
3733 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3734 exit(1);
3735 }
3736 }
3737
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003738 minlvl = 0; /* limit syslog level to this level (emerg) */
3739 if (*(args[4])) {
3740 minlvl = get_log_level(args[4]);
3741 if (level < 0) {
3742 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3743 exit(1);
3744 }
3745 }
3746
Robert Tsai81ae1952007-12-05 10:47:29 +01003747 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003748 struct sockaddr_un *sk = str2sun(args[1]);
3749 if (!sk) {
3750 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3751 args[1], (int)sizeof(sk->sun_path) - 1);
3752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
3754 }
3755 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003756 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003757 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003758 struct sockaddr_in *sk = str2sa(args[1]);
3759 if (!sk) {
3760 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
3763 }
3764 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003765 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003766 if (!logsrv.u.in.sin_port) {
3767 logsrv.u.in.sin_port =
3768 htons(SYSLOG_PORT);
3769 }
3770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771
3772 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003773 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 curproxy->logfac1 = facility;
3775 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003776 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 }
3778 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003779 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 curproxy->logfac2 = facility;
3781 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003782 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 }
3784 else {
3785 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 }
3789 }
3790 else {
3791 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3792 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 }
3796 }
3797 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003798 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003799 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003800
Willy Tarreau977b8e42006-12-29 14:19:17 +01003801 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003803
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003805 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3806 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003810
3811 /* we must first clear any optional default setting */
3812 curproxy->options &= ~PR_O_TPXY_MASK;
3813 free(curproxy->iface_name);
3814 curproxy->iface_name = NULL;
3815 curproxy->iface_len = 0;
3816
Willy Tarreaud5191e72010-02-09 20:50:45 +01003817 sk = str2sa(args[1]);
3818 if (!sk) {
3819 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
3823 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003825
3826 cur_arg = 2;
3827 while (*(args[cur_arg])) {
3828 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003829#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3830#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003831 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3832 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3833 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003836 }
3837#endif
3838 if (!*args[cur_arg + 1]) {
3839 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3840 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003843 }
3844
3845 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003846 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003847 curproxy->options |= PR_O_TPXY_CLI;
3848 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003849 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003850 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003851 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3852 char *name, *end;
3853
3854 name = args[cur_arg+1] + 7;
3855 while (isspace(*name))
3856 name++;
3857
3858 end = name;
3859 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3860 end++;
3861
3862 curproxy->options &= ~PR_O_TPXY_MASK;
3863 curproxy->options |= PR_O_TPXY_DYN;
3864 curproxy->bind_hdr_name = calloc(1, end - name + 1);
3865 curproxy->bind_hdr_len = end - name;
3866 memcpy(curproxy->bind_hdr_name, name, end - name);
3867 curproxy->bind_hdr_name[end-name] = '\0';
3868 curproxy->bind_hdr_occ = -1;
3869
3870 /* now look for an occurrence number */
3871 while (isspace(*end))
3872 end++;
3873 if (*end == ',') {
3874 end++;
3875 name = end;
3876 if (*end == '-')
3877 end++;
3878 while (isdigit(*end))
3879 end++;
3880 curproxy->bind_hdr_occ = strl2ic(name, end-name);
3881 }
3882
3883 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
3884 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3885 " occurrences values smaller than %d.\n",
3886 file, linenum, MAX_HDR_HISTORY);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003890 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003891 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3892 if (!sk) {
3893 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
3896 }
3897 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003898 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003899 }
3900 global.last_checks |= LSTCHK_NETADM;
3901#if !defined(CONFIG_HAP_LINUX_TPROXY)
3902 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003903#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003904#else /* no TPROXY support */
3905 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003906 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003909#endif
3910 cur_arg += 2;
3911 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003912 }
3913
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003914 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3915#ifdef SO_BINDTODEVICE
3916 if (!*args[cur_arg + 1]) {
3917 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3918 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003921 }
3922 if (curproxy->iface_name)
3923 free(curproxy->iface_name);
3924
3925 curproxy->iface_name = strdup(args[cur_arg + 1]);
3926 curproxy->iface_len = strlen(curproxy->iface_name);
3927 global.last_checks |= LSTCHK_NETADM;
3928#else
3929 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3930 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003933#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003934 cur_arg += 2;
3935 continue;
3936 }
3937 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3938 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003943 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3944 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3945 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003950 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3952 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003956
3957 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3958 ACL_DIR_REQ, ACT_REPLACE, 0,
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 Tarreaubaaee002006-06-26 02:48:02 +02003962 }
3963 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003964 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3965 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003966 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003967 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
3970 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003971 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3972 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003973 args[0], args[1], NULL, (const char **)args+2);
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], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003978 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3979 ACL_DIR_REQ, ACT_PASS, 0,
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], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003985 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3986 ACL_DIR_REQ, ACT_ALLOW, 0,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003991 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003992 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3993 ACL_DIR_REQ, ACT_TARPIT, 0,
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 Tarreaub8750a82006-09-03 09:56:00 +02003997 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003998 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003999 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4000 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004001 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004002 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004003 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004004 }
4005 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a 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_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004008 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004010 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004013 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004019
4020 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4021 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004022 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004023 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 }
4026 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004027 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4028 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004029 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004030 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 }
4033 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004034 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4035 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004036 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004037 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 }
4040 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004041 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4042 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004043 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004044 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 }
4047 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004048 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4049 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004050 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004051 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004054 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004055 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4056 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004057 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004058 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004059 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004062 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004063
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 if (curproxy == &defproxy) {
4065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004069 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004070 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 if (*(args[1]) == 0) {
4073 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004077
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004078 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4079 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4080 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4081 file, linenum, args[0]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4086 }
4087 else if (*args[2]) {
4088 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4089 file, linenum, args[0], args[2]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004094 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004095 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004096 wl->s = strdup(args[1]);
4097 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004098 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 }
4100 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004101 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004107
Willy Tarreauade5ec42010-01-28 19:33:49 +01004108 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4109 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004110 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004111 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 }
4114 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004115 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4116 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004117 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004118 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 }
4121 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004122 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4123 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004124 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004125 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 }
4128 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004129 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 }
4135
Willy Tarreauade5ec42010-01-28 19:33:49 +01004136 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4137 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004138 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004139 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 }
4142 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004143 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4144 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004145 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004146 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 }
4149 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004150 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4151 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004152 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004153 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 }
4156 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004157 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004158
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 if (curproxy == &defproxy) {
4160 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004164 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 if (*(args[1]) == 0) {
4168 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 }
4172
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004173 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4174 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4175 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4176 file, linenum, args[0]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
4180 err_code |= warnif_cond_requires_req(cond, file, linenum);
4181 }
4182 else if (*args[2]) {
4183 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4184 file, linenum, args[0], args[2]);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004189 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004190 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004191 wl->s = strdup(args[1]);
4192 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 }
4194 else if (!strcmp(args[0], "errorloc") ||
4195 !strcmp(args[0], "errorloc302") ||
4196 !strcmp(args[0], "errorloc303")) { /* error location */
4197 int errnum, errlen;
4198 char *err;
4199
Willy Tarreau977b8e42006-12-29 14:19:17 +01004200 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004202
Willy Tarreaubaaee002006-06-26 02:48:02 +02004203 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004204 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004207 }
4208
4209 errnum = atol(args[1]);
4210 if (!strcmp(args[0], "errorloc303")) {
4211 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4212 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4213 } else {
4214 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4215 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4216 }
4217
Willy Tarreau0f772532006-12-23 20:51:41 +01004218 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4219 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004220 chunk_destroy(&curproxy->errmsg[rc]);
4221 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004222 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004225
4226 if (rc >= HTTP_ERR_SIZE) {
4227 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4228 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 free(err);
4230 }
4231 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004232 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4233 int errnum, errlen, fd;
4234 char *err;
4235 struct stat stat;
4236
4237 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004239
4240 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004241 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004244 }
4245
4246 fd = open(args[2], O_RDONLY);
4247 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4248 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4249 file, linenum, args[2], args[1]);
4250 if (fd >= 0)
4251 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004254 }
4255
Willy Tarreau27a674e2009-08-17 07:23:33 +02004256 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004257 errlen = stat.st_size;
4258 } else {
4259 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004260 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004261 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004262 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004263 }
4264
4265 err = malloc(errlen); /* malloc() must succeed during parsing */
4266 errnum = read(fd, err, errlen);
4267 if (errnum != errlen) {
4268 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4269 file, linenum, args[2], args[1]);
4270 close(fd);
4271 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004274 }
4275 close(fd);
4276
4277 errnum = atol(args[1]);
4278 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4279 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004280 chunk_destroy(&curproxy->errmsg[rc]);
4281 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004282 break;
4283 }
4284 }
4285
4286 if (rc >= HTTP_ERR_SIZE) {
4287 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4288 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004289 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004290 free(err);
4291 }
4292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004294 struct cfg_kw_list *kwl;
4295 int index;
4296
4297 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4298 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4299 if (kwl->kw[index].section != CFG_LISTEN)
4300 continue;
4301 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4302 /* prepare error message just in case */
4303 snprintf(trash, sizeof(trash),
4304 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004305 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4306 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004307 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004310 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004311 else if (rc > 0) {
4312 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_WARN;
4314 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004315 }
Willy Tarreau93893792009-07-23 13:19:11 +02004316 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004317 }
4318 }
4319 }
4320
Willy Tarreau6daf3432008-01-22 16:44:08 +01004321 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 }
Willy Tarreau93893792009-07-23 13:19:11 +02004325 out:
4326 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327}
4328
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004329int
4330cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4331{
4332
4333 int err_code = 0;
4334 const char *err;
4335
4336 if (!strcmp(args[0], "userlist")) { /* new userlist */
4337 struct userlist *newul;
4338
4339 if (!*args[1]) {
4340 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4341 file, linenum, args[0]);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345
4346 err = invalid_char(args[1]);
4347 if (err) {
4348 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4349 file, linenum, *err, args[0], args[1]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353
4354 for (newul = userlist; newul; newul = newul->next)
4355 if (!strcmp(newul->name, args[1])) {
4356 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4357 file, linenum, args[1]);
4358 err_code |= ERR_WARN;
4359 goto out;
4360 }
4361
4362 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4363 if (!newul) {
4364 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4365 err_code |= ERR_ALERT | ERR_ABORT;
4366 goto out;
4367 }
4368
4369 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4370 newul->name = strdup(args[1]);
4371
4372 if (!newul->groupusers | !newul->name) {
4373 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4374 err_code |= ERR_ALERT | ERR_ABORT;
4375 goto out;
4376 }
4377
4378 newul->next = userlist;
4379 userlist = newul;
4380
4381 } else if (!strcmp(args[0], "group")) { /* new group */
4382 int cur_arg, i;
4383 const char *err;
4384
4385 if (!*args[1]) {
4386 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4387 file, linenum, args[0]);
4388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
4390 }
4391
4392 err = invalid_char(args[1]);
4393 if (err) {
4394 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4395 file, linenum, *err, args[0], args[1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399
4400 for(i = 0; i < userlist->grpcnt; i++)
4401 if (!strcmp(userlist->groups[i], args[1])) {
4402 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4403 file, linenum, args[1], userlist->name);
4404 err_code |= ERR_ALERT;
4405 goto out;
4406 }
4407
4408 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4409 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4410 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
4413 }
4414
4415 cur_arg = 2;
4416
4417 while (*args[cur_arg]) {
4418 if (!strcmp(args[cur_arg], "users")) {
4419 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4420 cur_arg += 2;
4421 continue;
4422 } else {
4423 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4424 file, linenum, args[0]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 }
4428 }
4429
4430 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4431 } else if (!strcmp(args[0], "user")) { /* new user */
4432 struct auth_users *newuser;
4433 int cur_arg;
4434
4435 if (!*args[1]) {
4436 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4437 file, linenum, args[0]);
4438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
4440 }
4441
4442 for (newuser = userlist->users; newuser; newuser = newuser->next)
4443 if (!strcmp(newuser->user, args[1])) {
4444 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4445 file, linenum, args[1], userlist->name);
4446 err_code |= ERR_ALERT;
4447 goto out;
4448 }
4449
4450 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4451 if (!newuser) {
4452 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4453 err_code |= ERR_ALERT | ERR_ABORT;
4454 goto out;
4455 }
4456
4457 newuser->user = strdup(args[1]);
4458
4459 newuser->next = userlist->users;
4460 userlist->users = newuser;
4461
4462 cur_arg = 2;
4463
4464 while (*args[cur_arg]) {
4465 if (!strcmp(args[cur_arg], "password")) {
4466#ifndef CONFIG_HAP_CRYPT
4467 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4468 file, linenum);
4469 err_code |= ERR_ALERT;
4470#endif
4471 newuser->pass = strdup(args[cur_arg + 1]);
4472 cur_arg += 2;
4473 continue;
4474 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4475 newuser->pass = strdup(args[cur_arg + 1]);
4476 newuser->flags |= AU_O_INSECURE;
4477 cur_arg += 2;
4478 continue;
4479 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004480 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004481 cur_arg += 2;
4482 continue;
4483 } else {
4484 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4485 file, linenum, args[0]);
4486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
4488 }
4489 }
4490 } else {
4491 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4492 err_code |= ERR_ALERT | ERR_FATAL;
4493 }
4494
4495out:
4496 return err_code;
4497}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498
4499/*
4500 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004501 * Returns the error code, 0 if OK, or any combination of :
4502 * - ERR_ABORT: must abort ASAP
4503 * - ERR_FATAL: we can continue parsing but not start the service
4504 * - ERR_WARN: a warning has been emitted
4505 * - ERR_ALERT: an alert has been emitted
4506 * Only the two first ones can stop processing, the two others are just
4507 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004509int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004511 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 FILE *f;
4513 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004515 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 if ((f=fopen(file,"r")) == NULL)
4518 return -1;
4519
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004520 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004521 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004522 char *end;
4523 char *args[MAX_LINE_ARGS + 1];
4524 char *line = thisline;
4525
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 linenum++;
4527
4528 end = line + strlen(line);
4529
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004530 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4531 /* Check if we reached the limit and the last char is not \n.
4532 * Watch out for the last line without the terminating '\n'!
4533 */
4534 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004535 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004537 }
4538
Willy Tarreaubaaee002006-06-26 02:48:02 +02004539 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004540 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 line++;
4542
4543 arg = 0;
4544 args[arg] = line;
4545
4546 while (*line && arg < MAX_LINE_ARGS) {
4547 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4548 * C equivalent value. Other combinations left unchanged (eg: \1).
4549 */
4550 if (*line == '\\') {
4551 int skip = 0;
4552 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4553 *line = line[1];
4554 skip = 1;
4555 }
4556 else if (line[1] == 'r') {
4557 *line = '\r';
4558 skip = 1;
4559 }
4560 else if (line[1] == 'n') {
4561 *line = '\n';
4562 skip = 1;
4563 }
4564 else if (line[1] == 't') {
4565 *line = '\t';
4566 skip = 1;
4567 }
4568 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004569 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004570 unsigned char hex1, hex2;
4571 hex1 = toupper(line[2]) - '0';
4572 hex2 = toupper(line[3]) - '0';
4573 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4574 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4575 *line = (hex1<<4) + hex2;
4576 skip = 3;
4577 }
4578 else {
4579 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 }
4582 }
4583 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004584 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004585 end -= skip;
4586 }
4587 line++;
4588 }
4589 else if (*line == '#' || *line == '\n' || *line == '\r') {
4590 /* end of string, end of loop */
4591 *line = 0;
4592 break;
4593 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004594 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004596 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004597 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 line++;
4599 args[++arg] = line;
4600 }
4601 else {
4602 line++;
4603 }
4604 }
4605
4606 /* empty line */
4607 if (!**args)
4608 continue;
4609
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004610 if (*line) {
4611 /* we had to stop due to too many args.
4612 * Let's terminate the string, print the offending part then cut the
4613 * last arg.
4614 */
4615 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4616 line++;
4617 *line = '\0';
4618
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004619 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004620 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 args[arg] = line;
4623 }
4624
Willy Tarreau540abe42007-05-02 20:50:16 +02004625 /* zero out remaining args and ensure that at least one entry
4626 * is zeroed out.
4627 */
4628 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004629 args[arg] = line;
4630 }
4631
Willy Tarreau3842f002009-06-14 11:39:52 +02004632 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004633 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004634 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004635 for (arg=0; *args[arg+1]; arg++)
4636 args[arg] = args[arg+1]; // shift args after inversion
4637 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004638 else if (!strcmp(args[0], "default")) {
4639 kwm = KWM_DEF;
4640 for (arg=0; *args[arg+1]; arg++)
4641 args[arg] = args[arg+1]; // shift args after inversion
4642 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004643
Willy Tarreau3842f002009-06-14 11:39:52 +02004644 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4645 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004646 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004647 }
4648
Willy Tarreau977b8e42006-12-29 14:19:17 +01004649 if (!strcmp(args[0], "listen") ||
4650 !strcmp(args[0], "frontend") ||
4651 !strcmp(args[0], "backend") ||
4652 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004653 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004654 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004655 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004656 cursection = strdup(args[0]);
4657 }
4658 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004660 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004661 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004662 } else if (!strcmp(args[0], "userlist")) {
4663 confsect = CFG_USERLIST;
4664 free(cursection);
4665 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 /* else it's a section keyword */
4668
4669 switch (confsect) {
4670 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004671 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 break;
4673 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004674 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004676 case CFG_USERLIST:
4677 err_code |= cfg_parse_users(file, linenum, args, kwm);
4678 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004680 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004681 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004682 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004683
4684 if (err_code & ERR_ABORT)
4685 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004687 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004688 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004690 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004691}
4692
Willy Tarreaubb925012009-07-23 13:36:36 +02004693/*
4694 * Returns the error code, 0 if OK, or any combination of :
4695 * - ERR_ABORT: must abort ASAP
4696 * - ERR_FATAL: we can continue parsing but not start the service
4697 * - ERR_WARN: a warning has been emitted
4698 * - ERR_ALERT: an alert has been emitted
4699 * Only the two first ones can stop processing, the two others are just
4700 * indicators.
4701 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004702int check_config_validity()
4703{
4704 int cfgerr = 0;
4705 struct proxy *curproxy = NULL;
4706 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004707 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004708 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004709 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710
4711 /*
4712 * Now, check for the integrity of all that we have collected.
4713 */
4714
4715 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004716 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004718 /* first, we will invert the proxy list order */
4719 curproxy = NULL;
4720 while (proxy) {
4721 struct proxy *next;
4722
4723 next = proxy->next;
4724 proxy->next = curproxy;
4725 curproxy = proxy;
4726 if (!next)
4727 break;
4728 proxy = next;
4729 }
4730
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004732 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 }
4736
4737 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004738 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004739 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02004740 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004741 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004742 unsigned int next_id;
4743
4744 if (!curproxy->uuid) {
4745 /* proxy ID not set, use automatic numbering with first
4746 * spare entry starting with next_pxid.
4747 */
4748 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4749 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4750 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004751 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004752 next_pxid++;
4753
Willy Tarreau55ea7572007-06-17 19:56:27 +02004754
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004756 /* ensure we don't keep listeners uselessly bound */
4757 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 curproxy = curproxy->next;
4759 continue;
4760 }
4761
Willy Tarreauff01a212009-03-15 13:46:16 +01004762 switch (curproxy->mode) {
4763 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004764 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004765 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004766 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4767 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004768 cfgerr++;
4769 }
4770
4771 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004772 Warning("config : servers will be ignored for %s '%s'.\n",
4773 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004774 break;
4775
4776 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004777 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004778 break;
4779
4780 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004781 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004782 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004783 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4784 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004785 cfgerr++;
4786 }
4787 break;
4788 }
4789
4790 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004791 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4792 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 cfgerr++;
4794 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004795
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004796 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004797 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004798 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004799 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4800 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004801 cfgerr++;
4802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004804 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004805 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4806 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004807 cfgerr++;
4808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004810 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004811 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4812 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004813 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004814 }
4815 }
4816 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4817 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4818 /* If no LB algo is set in a backend, and we're not in
4819 * transparent mode, dispatch mode nor proxy mode, we
4820 * want to use balance roundrobin by default.
4821 */
4822 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4823 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
4825 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004826
Willy Tarreau82936582007-11-30 15:20:09 +01004827 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4828 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004829 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4830 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004831 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004832 }
4833
Willy Tarreauef781042010-01-27 11:53:01 +01004834 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4835 curproxy->options &= ~PR_O2_CHK_SNDST;
4836 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4837 "send-state", proxy_type_str(curproxy), curproxy->id);
4838 err_code |= ERR_WARN;
4839 }
4840
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004841 /* if a default backend was specified, let's find it */
4842 if (curproxy->defbe.name) {
4843 struct proxy *target;
4844
Alex Williams96532db2009-11-01 21:27:13 -05004845 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004846 if (!target) {
4847 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4848 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004849 cfgerr++;
4850 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004851 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4852 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004853 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004854 } else {
4855 free(curproxy->defbe.name);
4856 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004857 /* we force the backend to be present on at least all of
4858 * the frontend's processes.
4859 */
4860 target->bind_proc = curproxy->bind_proc ?
4861 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
4863 }
4864
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004865 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004866 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4867 /* map jump target for ACT_SETBE in req_rep chain */
4868 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004869 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004870 struct proxy *target;
4871
Willy Tarreaua496b602006-12-17 23:15:24 +01004872 if (exp->action != ACT_SETBE)
4873 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004874
Alex Williams96532db2009-11-01 21:27:13 -05004875 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004876 if (!target) {
4877 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4878 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004879 cfgerr++;
4880 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004881 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4882 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004883 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004884 } else {
4885 free((void *)exp->replace);
4886 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004887 /* we force the backend to be present on at least all of
4888 * the frontend's processes.
4889 */
4890 target->bind_proc = curproxy->bind_proc ?
4891 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004892 }
4893 }
4894 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004895
4896 /* find the target proxy for 'use_backend' rules */
4897 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004898 struct proxy *target;
4899
Alex Williams96532db2009-11-01 21:27:13 -05004900 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004901
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004902 if (!target) {
4903 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4904 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004905 cfgerr++;
4906 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004907 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4908 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004909 cfgerr++;
4910 } else {
4911 free((void *)rule->be.name);
4912 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004913 /* we force the backend to be present on at least all of
4914 * the frontend's processes.
4915 */
4916 target->bind_proc = curproxy->bind_proc ?
4917 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004918 }
4919 }
4920
Emeric Brunb982a3d2010-01-04 15:45:53 +01004921 /* find the target table for 'stick' rules */
4922 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4923 struct proxy *target;
4924
Emeric Brun1d33b292010-01-04 15:47:17 +01004925 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4926 if (mrule->flags & STK_IS_STORE)
4927 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4928
Emeric Brunb982a3d2010-01-04 15:45:53 +01004929 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02004930 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004931 else
4932 target = curproxy;
4933
4934 if (!target) {
4935 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4936 curproxy->id, mrule->table.name);
4937 cfgerr++;
4938 }
4939 else if (target->table.size == 0) {
4940 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4941 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4942 cfgerr++;
4943 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02004944 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004945 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4946 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4947 cfgerr++;
4948 }
4949 else {
4950 free((void *)mrule->table.name);
4951 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02004952 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004953 }
4954 }
4955
4956 /* find the target table for 'store response' rules */
4957 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4958 struct proxy *target;
4959
Emeric Brun1d33b292010-01-04 15:47:17 +01004960 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4961
Emeric Brunb982a3d2010-01-04 15:45:53 +01004962 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02004963 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004964 else
4965 target = curproxy;
4966
4967 if (!target) {
4968 Alert("Proxy '%s': unable to find store table '%s'.\n",
4969 curproxy->id, mrule->table.name);
4970 cfgerr++;
4971 }
4972 else if (target->table.size == 0) {
4973 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4974 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4975 cfgerr++;
4976 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02004977 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004978 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4979 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4980 cfgerr++;
4981 }
4982 else {
4983 free((void *)mrule->table.name);
4984 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02004985 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004986 }
4987 }
4988
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02004989 /* find the target table for 'tcp-request' layer 4 rules */
4990 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
4991 struct proxy *target;
4992
Willy Tarreauf059a0f2010-08-03 16:29:52 +02004993 if (trule->action != TCP_ACT_TRK_FE_CTR && trule->action != TCP_ACT_TRK_BE_CTR)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02004994 continue;
4995
4996 if (trule->act_prm.trk_ctr.table.n)
4997 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
4998 else
4999 target = curproxy;
5000
5001 if (!target) {
5002 Alert("Proxy '%s': unable to find table '%s' referenced by track-counter.\n",
5003 curproxy->id, trule->act_prm.trk_ctr.table.n);
5004 cfgerr++;
5005 }
5006 else if (target->table.size == 0) {
5007 Alert("Proxy '%s': table '%s' used but not configured.\n",
5008 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5009 cfgerr++;
5010 }
5011 else if (trule->act_prm.trk_ctr.type != target->table.type) {
5012 Alert("Proxy '%s': type of track-counters pattern not usable with type of stick-table '%s'.\n",
5013 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5014 cfgerr++;
5015 }
5016 else {
5017 free(trule->act_prm.trk_ctr.table.n);
5018 trule->act_prm.trk_ctr.table.t = &target->table;
5019 /* Note: if we decide to enhance the track-counters syntax, we may be able
5020 * to pass a list of counters to track and allocate them right here using
5021 * stktable_alloc_data_type().
5022 */
5023 }
5024 }
5025
Willy Tarreaud1f96522010-08-03 19:34:32 +02005026 /* find the target table for 'tcp-request' layer 6 rules */
5027 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5028 struct proxy *target;
5029
5030 if (trule->action != TCP_ACT_TRK_FE_CTR && trule->action != TCP_ACT_TRK_BE_CTR)
5031 continue;
5032
5033 if (trule->act_prm.trk_ctr.table.n)
5034 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5035 else
5036 target = curproxy;
5037
5038 if (!target) {
5039 Alert("Proxy '%s': unable to find table '%s' referenced by track-counter.\n",
5040 curproxy->id, trule->act_prm.trk_ctr.table.n);
5041 cfgerr++;
5042 }
5043 else if (target->table.size == 0) {
5044 Alert("Proxy '%s': table '%s' used but not configured.\n",
5045 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5046 cfgerr++;
5047 }
5048 else if (trule->act_prm.trk_ctr.type != target->table.type) {
5049 Alert("Proxy '%s': type of track-counters pattern not usable with type of stick-table '%s'.\n",
5050 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5051 cfgerr++;
5052 }
5053 else {
5054 free(trule->act_prm.trk_ctr.table.n);
5055 trule->act_prm.trk_ctr.table.t = &target->table;
5056 /* Note: if we decide to enhance the track-counters syntax, we may be able
5057 * to pass a list of counters to track and allocate them right here using
5058 * stktable_alloc_data_type().
5059 */
5060 }
5061 }
5062
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005063 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5064 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005065 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5066 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5067 "proxy", curproxy->id);
5068 cfgerr++;
5069 goto out_uri_auth_compat;
5070 }
5071
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005072 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005073 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005074 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005075 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005076
Willy Tarreau95fa4692010-02-01 13:05:50 +01005077 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5078 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005079
5080 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005081 uri_auth_compat_req[i++] = "realm";
5082 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5083 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005084
Willy Tarreau95fa4692010-02-01 13:05:50 +01005085 uri_auth_compat_req[i++] = "unless";
5086 uri_auth_compat_req[i++] = "{";
5087 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5088 uri_auth_compat_req[i++] = "}";
5089 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005090
Willy Tarreau95fa4692010-02-01 13:05:50 +01005091 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5092 if (!req_acl) {
5093 cfgerr++;
5094 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005095 }
5096
Willy Tarreau95fa4692010-02-01 13:05:50 +01005097 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5098
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005099 if (curproxy->uri_auth->auth_realm) {
5100 free(curproxy->uri_auth->auth_realm);
5101 curproxy->uri_auth->auth_realm = NULL;
5102 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005103
5104 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005105 }
5106out_uri_auth_compat:
5107
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005108 cfgerr += acl_find_targets(curproxy);
5109
Willy Tarreau2738a142006-07-08 17:28:09 +02005110 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005111 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005112 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005113 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005114 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005115 " | While not properly invalid, you will certainly encounter various problems\n"
5116 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005117 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005118 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005119 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005120 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005121
Willy Tarreau1fa31262007-12-03 00:36:16 +01005122 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5123 * We must still support older configurations, so let's find out whether those
5124 * parameters have been set or must be copied from contimeouts.
5125 */
5126 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005127 if (!curproxy->timeout.tarpit ||
5128 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005129 /* tarpit timeout not set. We search in the following order:
5130 * default.tarpit, curr.connect, default.connect.
5131 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005132 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005133 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005134 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005135 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005136 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005137 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005138 }
5139 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005140 (!curproxy->timeout.queue ||
5141 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005142 /* queue timeout not set. We search in the following order:
5143 * default.queue, curr.connect, default.connect.
5144 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005145 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005146 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005147 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005148 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005149 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005150 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005151 }
5152 }
5153
Willy Tarreau07a54902010-03-29 18:33:29 +02005154 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005155 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5156 curproxy->check_req = (char *)malloc(curproxy->check_len);
5157 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005158 }
5159
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005160 /* The small pools required for the capture lists */
5161 if (curproxy->nb_req_cap)
5162 curproxy->req_cap_pool = create_pool("ptrcap",
5163 curproxy->nb_req_cap * sizeof(char *),
5164 MEM_F_SHARED);
5165 if (curproxy->nb_rsp_cap)
5166 curproxy->rsp_cap_pool = create_pool("ptrcap",
5167 curproxy->nb_rsp_cap * sizeof(char *),
5168 MEM_F_SHARED);
5169
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005170 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5171 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5172 MEM_F_SHARED);
5173
Willy Tarreau86034312006-12-29 00:10:33 +01005174 /* for backwards compatibility with "listen" instances, if
5175 * fullconn is not set but maxconn is set, then maxconn
5176 * is used.
5177 */
5178 if (!curproxy->fullconn)
5179 curproxy->fullconn = curproxy->maxconn;
5180
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 /* first, we will invert the servers list order */
5182 newsrv = NULL;
5183 while (curproxy->srv) {
5184 struct server *next;
5185
5186 next = curproxy->srv->next;
5187 curproxy->srv->next = newsrv;
5188 newsrv = curproxy->srv;
5189 if (!next)
5190 break;
5191 curproxy->srv = next;
5192 }
5193
Willy Tarreaudd701652010-05-25 23:03:02 +02005194 /* assign automatic UIDs to servers which don't have one yet */
5195 next_id = 1;
5196 newsrv = curproxy->srv;
5197 while (newsrv != NULL) {
5198 if (!newsrv->puid) {
5199 /* server ID not set, use automatic numbering with first
5200 * spare entry starting with next_svid.
5201 */
5202 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5203 newsrv->conf.id.key = newsrv->puid = next_id;
5204 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5205 }
5206 next_id++;
5207 newsrv = newsrv->next;
5208 }
5209
Willy Tarreau20697042007-11-15 23:26:18 +01005210 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005211 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005213 /* We have to initialize the server lookup mechanism depending
5214 * on what LB algorithm was choosen.
5215 */
5216
5217 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5218 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5219 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005220 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5221 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5222 init_server_map(curproxy);
5223 } else {
5224 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5225 fwrr_init_server_groups(curproxy);
5226 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005227 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005228
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005229 case BE_LB_KIND_LC:
5230 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005231 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005232 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005233
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005234 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005235 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5236 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5237 chash_init_server_tree(curproxy);
5238 } else {
5239 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5240 init_server_map(curproxy);
5241 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005242 break;
5243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244
5245 if (curproxy->options & PR_O_LOGASAP)
5246 curproxy->to_log &= ~LW_BYTES;
5247
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005248 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5249 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5250 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5251 proxy_type_str(curproxy), curproxy->id);
5252 err_code |= ERR_WARN;
5253 }
5254
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005255 if (curproxy->mode != PR_MODE_HTTP) {
5256 int optnum;
5257
5258 if (curproxy->options & PR_O_COOK_ANY) {
5259 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5260 proxy_type_str(curproxy), curproxy->id);
5261 err_code |= ERR_WARN;
5262 }
5263
5264 if (curproxy->uri_auth) {
5265 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5266 proxy_type_str(curproxy), curproxy->id);
5267 err_code |= ERR_WARN;
5268 curproxy->uri_auth = NULL;
5269 }
5270
5271 if (curproxy->options & PR_O_FWDFOR) {
5272 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5273 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5274 err_code |= ERR_WARN;
5275 curproxy->options &= ~PR_O_FWDFOR;
5276 }
5277
5278 if (curproxy->options & PR_O_ORGTO) {
5279 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5280 "originalto", proxy_type_str(curproxy), curproxy->id);
5281 err_code |= ERR_WARN;
5282 curproxy->options &= ~PR_O_ORGTO;
5283 }
5284
5285 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5286 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5287 (curproxy->cap & cfg_opts[optnum].cap) &&
5288 (curproxy->options & cfg_opts[optnum].val)) {
5289 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5290 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5291 err_code |= ERR_WARN;
5292 curproxy->options &= ~cfg_opts[optnum].val;
5293 }
5294 }
5295
5296 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5297 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5298 (curproxy->cap & cfg_opts2[optnum].cap) &&
5299 (curproxy->options2 & cfg_opts2[optnum].val)) {
5300 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5301 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5302 err_code |= ERR_WARN;
5303 curproxy->options2 &= ~cfg_opts2[optnum].val;
5304 }
5305 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005306
Willy Tarreauefa5f512010-03-30 20:13:29 +02005307#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005308 if (curproxy->bind_hdr_occ) {
5309 curproxy->bind_hdr_occ = 0;
5310 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5311 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5312 err_code |= ERR_WARN;
5313 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005314#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005315 }
5316
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005318 * ensure that we're not cross-dressing a TCP server into HTTP.
5319 */
5320 newsrv = curproxy->srv;
5321 while (newsrv != NULL) {
5322 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005323 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5324 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005325 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005326 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005327
Willy Tarreauefa5f512010-03-30 20:13:29 +02005328#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005329 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5330 newsrv->bind_hdr_occ = 0;
5331 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5332 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5333 err_code |= ERR_WARN;
5334 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005335#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005336 newsrv = newsrv->next;
5337 }
5338
5339 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 * If this server supports a maxconn parameter, it needs a dedicated
5341 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005342 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 */
5344 newsrv = curproxy->srv;
5345 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005346 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 /* Only 'minconn' was specified, or it was higher than or equal
5348 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5349 * this will avoid further useless expensive computations.
5350 */
5351 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005352 } else if (newsrv->maxconn && !newsrv->minconn) {
5353 /* minconn was not specified, so we set it to maxconn */
5354 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005355 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005356 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5357 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005358 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 }
5360
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005361 if (newsrv->trackit) {
5362 struct proxy *px;
5363 struct server *srv;
5364 char *pname, *sname;
5365
5366 pname = newsrv->trackit;
5367 sname = strrchr(pname, '/');
5368
5369 if (sname)
5370 *sname++ = '\0';
5371 else {
5372 sname = pname;
5373 pname = NULL;
5374 }
5375
5376 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005377 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005378 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005379 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5380 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005381 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005382 cfgerr++;
5383 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005384 }
5385 } else
5386 px = curproxy;
5387
5388 srv = findserver(px, sname);
5389 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005390 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5391 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005392 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005393 cfgerr++;
5394 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005395 }
5396
5397 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005398 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005399 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005400 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005401 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005402 cfgerr++;
5403 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005404 }
5405
5406 if (curproxy != px &&
5407 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005408 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005409 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005410 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005411 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005412 cfgerr++;
5413 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005414 }
5415
5416 newsrv->tracked = srv;
5417 newsrv->tracknext = srv->tracknext;
5418 srv->tracknext = newsrv;
5419
5420 free(newsrv->trackit);
5421 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005422 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 newsrv = newsrv->next;
5424 }
5425
Willy Tarreauc1a21672009-08-16 22:37:44 +02005426 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005427 curproxy->accept = frontend_accept;
5428
Willy Tarreauc1a21672009-08-16 22:37:44 +02005429 if (curproxy->tcp_req.inspect_delay ||
5430 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02005431 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005432
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005433 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005434 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005435 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005436 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005437
5438 /* both TCP and HTTP must check switching rules */
5439 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5440 }
5441
5442 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02005443 if (curproxy->tcp_req.inspect_delay ||
5444 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5445 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
5446
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005447 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005448 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005449 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005450 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005451
5452 /* If the backend does requires RDP cookie persistence, we have to
5453 * enable the corresponding analyser.
5454 */
5455 if (curproxy->options2 & PR_O2_RDPC_PRST)
5456 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5457 }
5458
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005459 listener = NULL;
5460 while (curproxy->listen) {
5461 struct listener *next;
5462
5463 next = curproxy->listen->next;
5464 curproxy->listen->next = listener;
5465 listener = curproxy->listen;
5466
5467 if (!next)
5468 break;
5469
5470 curproxy->listen = next;
5471 }
5472
Willy Tarreaue6b98942007-10-29 01:09:36 +01005473 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005474 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005475 listener = curproxy->listen;
5476 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005477 if (!listener->luid) {
5478 /* listener ID not set, use automatic numbering with first
5479 * spare entry starting with next_luid.
5480 */
5481 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5482 listener->conf.id.key = listener->luid = next_id;
5483 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005484 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005485 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005486
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005487 /* enable separate counters */
5488 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5489 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5490 if (!listener->name) {
5491 sprintf(trash, "sock-%d", listener->luid);
5492 listener->name = strdup(trash);
5493 }
5494 }
5495
Willy Tarreaue6b98942007-10-29 01:09:36 +01005496 if (curproxy->options & PR_O_TCP_NOLING)
5497 listener->options |= LI_O_NOLINGER;
5498 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005499 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005500 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005501 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02005502 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005503 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005504 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005505
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02005506 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
5507 listener->options |= LI_O_TCP_RULES;
5508
Willy Tarreaude3041d2010-05-31 10:56:17 +02005509 if (curproxy->mon_mask.s_addr)
5510 listener->options |= LI_O_CHK_MONNET;
5511
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005512 /* smart accept mode is automatic in HTTP mode */
5513 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5514 (curproxy->mode == PR_MODE_HTTP &&
5515 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5516 listener->options |= LI_O_NOQUICKACK;
5517
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005518 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005519 listener = listener->next;
5520 }
5521
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 curproxy = curproxy->next;
5523 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005524
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005525 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5526 struct auth_users *curuser;
5527 int g;
5528
5529 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5530 unsigned int group_mask = 0;
5531 char *group = NULL;
5532
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005533 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005534 continue;
5535
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005536 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005537
5538 for (g = 0; g < curuserlist->grpcnt; g++)
5539 if (!strcmp(curuserlist->groups[g], group))
5540 break;
5541
5542 if (g == curuserlist->grpcnt) {
5543 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5544 curuserlist->name, group, curuser->user);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 }
5548
5549 group_mask |= (1 << g);
5550 }
5551
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005552 free(curuser->u.groups);
5553 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005554 }
5555
5556 for (g = 0; g < curuserlist->grpcnt; g++) {
5557 char *user = NULL;
5558
5559 if (!curuserlist->groupusers[g])
5560 continue;
5561
5562 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5563 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5564 if (!strcmp(curuser->user, user))
5565 break;
5566
5567 if (!curuser) {
5568 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5569 curuserlist->name, user, curuserlist->groups[g]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005574 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005575 }
5576
5577 free(curuserlist->groupusers[g]);
5578 }
5579
5580 free(curuserlist->groupusers);
5581
5582#ifdef DEBUG_AUTH
5583 for (g = 0; g < curuserlist->grpcnt; g++) {
5584 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5585
5586 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5587 if (curuser->group_mask & (1 << g))
5588 fprintf(stderr, " %s", curuser->user);
5589 }
5590
5591 fprintf(stderr, "\n");
5592 }
5593#endif
5594
5595 }
5596
Willy Tarreau056f5682010-06-06 15:51:11 +02005597 /* initialize stick-tables on backend capable proxies. This must not
5598 * be done earlier because the data size may be discovered while parsing
5599 * other proxies.
5600 */
5601 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005602 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02005603
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005604 /*
5605 * Recount currently required checks.
5606 */
5607
5608 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5609 int optnum;
5610
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005611 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5612 if (curproxy->options & cfg_opts[optnum].val)
5613 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005614
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005615 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5616 if (curproxy->options2 & cfg_opts2[optnum].val)
5617 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005618 }
5619
Willy Tarreaubb925012009-07-23 13:36:36 +02005620 if (cfgerr > 0)
5621 err_code |= ERR_ALERT | ERR_FATAL;
5622 out:
5623 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624}
5625
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005626/*
5627 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5628 * parsing sessions.
5629 */
5630void cfg_register_keywords(struct cfg_kw_list *kwl)
5631{
5632 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5633}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005635/*
5636 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5637 */
5638void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5639{
5640 LIST_DEL(&kwl->list);
5641 LIST_INIT(&kwl->list);
5642}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643
5644/*
5645 * Local variables:
5646 * c-indent-level: 8
5647 * c-basic-offset: 8
5648 * End:
5649 */