blob: a7cdea4d5a68931b1b8b1da79a2237191a594fa8 [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 Tarreauaf7ad002010-08-31 15:39:26 +0200270 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100271 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 } /* end for(port) */
273 } /* end while(next) */
274 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200275 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 fail:
277 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200278 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200279}
280
Willy Tarreau977b8e42006-12-29 14:19:17 +0100281/*
282 * Sends a warning if proxy <proxy> does not have at least one of the
283 * capabilities in <cap>. An optionnal <hint> may be added at the end
284 * of the warning to help the user. Returns 1 if a warning was emitted
285 * or 0 if the condition is valid.
286 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100287int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100288{
289 char *msg;
290
291 switch (cap) {
292 case PR_CAP_BE: msg = "no backend"; break;
293 case PR_CAP_FE: msg = "no frontend"; break;
294 case PR_CAP_RS: msg = "no ruleset"; break;
295 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
296 default: msg = "not enough"; break;
297 }
298
299 if (!(proxy->cap & cap)) {
300 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100301 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302 return 1;
303 }
304 return 0;
305}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306
Willy Tarreau61d18892009-03-31 10:49:21 +0200307/* Report a warning if a rule is placed after a 'block' rule.
308 * Return 1 if the warning has been emitted, otherwise 0.
309 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100310int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200311{
312 if (!LIST_ISEMPTY(&proxy->block_cond)) {
313 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
314 file, line, arg);
315 return 1;
316 }
317 return 0;
318}
319
320/* Report a warning if a rule is placed after a reqrewrite rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
325 if (proxy->req_exp) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a reqadd rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100338 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* Report a warning if a rule is placed after a redirect rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a 'use_backend' rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
376 warnif_rule_after_reqadd(proxy, file, line, arg) ||
377 warnif_rule_after_redirect(proxy, file, line, arg) ||
378 warnif_rule_after_use_backend(proxy, file, line, arg);
379}
380
381/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100382int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200383{
384 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
385 warnif_rule_after_redirect(proxy, file, line, arg) ||
386 warnif_rule_after_use_backend(proxy, file, line, arg);
387}
388
389/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
392 return warnif_rule_after_redirect(proxy, file, line, arg) ||
393 warnif_rule_after_use_backend(proxy, file, line, arg);
394}
395
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100396/* Report it if a request ACL condition uses some response-only parameters. It
397 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
398 * Note that <cond> may be NULL and then will be ignored.
399 */
400static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
401{
402 struct acl *acl;
403
404 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
405 return 0;
406
407 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
408 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
409 file, line, acl ? acl->name : "(unknown)");
410 return ERR_WARN;
411}
412
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100413/* Report it if a request ACL condition uses some request-only volatile parameters.
414 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
415 * Note that <cond> may be NULL and then will be ignored.
416 */
417static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
418{
419 struct acl *acl;
420
421 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
422 return 0;
423
424 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
425 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
426 file, line, acl ? acl->name : "(unknown)");
427 return ERR_WARN;
428}
429
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100430
Willy Tarreaubaaee002006-06-26 02:48:02 +0200431/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200432 * parse a line in a <global> section. Returns the error code, 0 if OK, or
433 * any combination of :
434 * - ERR_ABORT: must abort ASAP
435 * - ERR_FATAL: we can continue parsing but not start the service
436 * - ERR_WARN: a warning has been emitted
437 * - ERR_ALERT: an alert has been emitted
438 * Only the two first ones can stop processing, the two others are just
439 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200441int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442{
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444
445 if (!strcmp(args[0], "global")) { /* new section */
446 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200448 }
449 else if (!strcmp(args[0], "daemon")) {
450 global.mode |= MODE_DAEMON;
451 }
452 else if (!strcmp(args[0], "debug")) {
453 global.mode |= MODE_DEBUG;
454 }
455 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100456 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200458 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100459 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200460 }
461 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100462 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100465 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100467 else if (!strcmp(args[0], "nosplice")) {
468 global.tune.options &= ~GTUNE_USE_SPLICE;
469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 else if (!strcmp(args[0], "quiet")) {
471 global.mode |= MODE_QUIET;
472 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200473 else if (!strcmp(args[0], "tune.maxpollevents")) {
474 if (global.tune.maxpollevents != 0) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200476 err_code |= ERR_ALERT;
477 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200483 }
484 global.tune.maxpollevents = atol(args[1]);
485 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100486 else if (!strcmp(args[0], "tune.maxaccept")) {
487 if (global.tune.maxaccept != 0) {
488 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT;
490 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100491 }
492 if (*(args[1]) == 0) {
493 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT | ERR_FATAL;
495 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100496 }
497 global.tune.maxaccept = atol(args[1]);
498 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200499 else if (!strcmp(args[0], "tune.chksize")) {
500 if (*(args[1]) == 0) {
501 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504 }
505 global.tune.chksize = atol(args[1]);
506 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200507 else if (!strcmp(args[0], "tune.bufsize")) {
508 if (*(args[1]) == 0) {
509 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
510 err_code |= ERR_ALERT | ERR_FATAL;
511 goto out;
512 }
513 global.tune.bufsize = atol(args[1]);
514 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
515 global.tune.maxrewrite = global.tune.bufsize / 2;
516 }
517 else if (!strcmp(args[0], "tune.maxrewrite")) {
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
522 }
523 global.tune.maxrewrite = atol(args[1]);
524 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
525 global.tune.maxrewrite = global.tune.bufsize / 2;
526 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100527 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
528 if (global.tune.client_rcvbuf != 0) {
529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
530 err_code |= ERR_ALERT;
531 goto out;
532 }
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
537 }
538 global.tune.client_rcvbuf = atol(args[1]);
539 }
540 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
541 if (global.tune.server_rcvbuf != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT;
544 goto out;
545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
550 }
551 global.tune.server_rcvbuf = atol(args[1]);
552 }
553 else if (!strcmp(args[0], "tune.sndbuf.client")) {
554 if (global.tune.client_sndbuf != 0) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.client_sndbuf = atol(args[1]);
565 }
566 else if (!strcmp(args[0], "tune.sndbuf.server")) {
567 if (global.tune.server_sndbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.server_sndbuf = atol(args[1]);
578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 else if (!strcmp(args[0], "uid")) {
580 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200581 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200582 err_code |= ERR_ALERT;
583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
590 global.uid = atol(args[1]);
591 }
592 else if (!strcmp(args[0], "gid")) {
593 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200594 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200595 err_code |= ERR_ALERT;
596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
603 global.gid = atol(args[1]);
604 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 /* user/group name handling */
606 else if (!strcmp(args[0], "user")) {
607 struct passwd *ha_user;
608 if (global.uid != 0) {
609 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 err_code |= ERR_ALERT;
611 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200612 }
613 errno = 0;
614 ha_user = getpwnam(args[1]);
615 if (ha_user != NULL) {
616 global.uid = (int)ha_user->pw_uid;
617 }
618 else {
619 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 +0200620 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200621 }
622 }
623 else if (!strcmp(args[0], "group")) {
624 struct group *ha_group;
625 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200626 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200629 }
630 errno = 0;
631 ha_group = getgrnam(args[1]);
632 if (ha_group != NULL) {
633 global.gid = (int)ha_group->gr_gid;
634 }
635 else {
636 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 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200638 }
639 }
640 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 else if (!strcmp(args[0], "nbproc")) {
642 if (global.nbproc != 0) {
643 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200644 err_code |= ERR_ALERT;
645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
652 global.nbproc = atol(args[1]);
653 }
654 else if (!strcmp(args[0], "maxconn")) {
655 if (global.maxconn != 0) {
656 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200657 err_code |= ERR_ALERT;
658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 }
665 global.maxconn = atol(args[1]);
666#ifdef SYSTEM_MAXCONN
667 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
668 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);
669 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 }
672#endif /* SYSTEM_MAXCONN */
673 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100674 else if (!strcmp(args[0], "maxpipes")) {
675 if (global.maxpipes != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100684 }
685 global.maxpipes = atol(args[1]);
686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 else if (!strcmp(args[0], "ulimit-n")) {
688 if (global.rlimit_nofile != 0) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697 }
698 global.rlimit_nofile = atol(args[1]);
699 }
700 else if (!strcmp(args[0], "chroot")) {
701 if (global.chroot != NULL) {
702 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200703 err_code |= ERR_ALERT;
704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 }
706 if (*(args[1]) == 0) {
707 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711 global.chroot = strdup(args[1]);
712 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200713 else if (!strcmp(args[0], "description")) {
714 int i, len=0;
715 char *d;
716
717 if (!*args[1]) {
718 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
719 file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723
724 for(i=1; *args[i]; i++)
725 len += strlen(args[i])+1;
726
727 if (global.desc)
728 free(global.desc);
729
730 global.desc = d = (char *)calloc(1, len);
731
732 d += sprintf(d, "%s", args[1]);
733 for(i=2; *args[i]; i++)
734 d += sprintf(d, " %s", args[i]);
735 }
736 else if (!strcmp(args[0], "node")) {
737 int i;
738 char c;
739
740 for (i=0; args[1][i]; i++) {
741 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100742 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
743 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200744 break;
745 }
746
747 if (!i || args[1][i]) {
748 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
749 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
750 file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754
755 if (global.node)
756 free(global.node);
757
758 global.node = strdup(args[1]);
759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 else if (!strcmp(args[0], "pidfile")) {
761 if (global.pidfile != NULL) {
762 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200763 err_code |= ERR_ALERT;
764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765 }
766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 global.pidfile = strdup(args[1]);
772 }
773 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100774 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200775 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776
777 if (*(args[1]) == 0 || *(args[2]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782
783 facility = get_log_facility(args[2]);
784 if (facility < 0) {
785 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200786 err_code |= ERR_ALERT | ERR_FATAL;
787 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788 }
789
790 level = 7; /* max syslog level = debug */
791 if (*(args[3])) {
792 level = get_log_level(args[3]);
793 if (level < 0) {
794 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 err_code |= ERR_ALERT | ERR_FATAL;
796 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797 }
798 }
799
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200800 minlvl = 0; /* limit syslog level to this level (emerg) */
801 if (*(args[4])) {
802 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200803 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200804 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT | ERR_FATAL;
806 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200807 }
808 }
809
Robert Tsai81ae1952007-12-05 10:47:29 +0100810 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100811 struct sockaddr_un *sk = str2sun(args[1]);
812 if (!sk) {
813 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
814 args[1], (int)sizeof(sk->sun_path) - 1);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100819 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100820 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100821 struct sockaddr_in *sk = str2sa(args[1]);
822 if (!sk) {
823 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
826 }
827 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100828 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100829 if (!logsrv.u.in.sin_port)
830 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832
833 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100834 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 global.logfac1 = facility;
836 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200837 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 }
839 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100840 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 global.logfac2 = facility;
842 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200843 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845 else {
846 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200849 }
850 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
851 if (global.spread_checks != 0) {
852 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200853 err_code |= ERR_ALERT;
854 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200855 }
856 if (*(args[1]) == 0) {
857 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200858 err_code |= ERR_ALERT | ERR_FATAL;
859 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200860 }
861 global.spread_checks = atol(args[1]);
862 if (global.spread_checks < 0 || global.spread_checks > 50) {
863 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 }
867 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200868 struct cfg_kw_list *kwl;
869 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200870 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200871
872 list_for_each_entry(kwl, &cfg_keywords.list, list) {
873 for (index = 0; kwl->kw[index].kw != NULL; index++) {
874 if (kwl->kw[index].section != CFG_GLOBAL)
875 continue;
876 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
877 /* prepare error message just in case */
878 snprintf(trash, sizeof(trash),
879 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200880 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
881 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200882 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200884 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200885 else if (rc > 0) {
886 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_WARN;
888 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200889 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200891 }
892 }
893 }
894
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200898
Willy Tarreau058e9072009-07-20 09:30:05 +0200899 out:
900 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901}
902
Willy Tarreau97cb7802010-01-03 20:23:58 +0100903/* Perform the most basic initialization of a proxy :
904 * memset(), list_init(*), reset_timeouts(*).
905 */
906static void init_new_proxy(struct proxy *p)
907{
908 memset(p, 0, sizeof(struct proxy));
909 LIST_INIT(&p->pendconns);
910 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100911 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100912 LIST_INIT(&p->block_cond);
913 LIST_INIT(&p->redirect_rules);
914 LIST_INIT(&p->mon_fail_cond);
915 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +0200916 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100917 LIST_INIT(&p->sticking_rules);
918 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100919 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +0200920 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100921 LIST_INIT(&p->req_add);
922 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100923
924 /* Timeouts are defined as -1 */
925 proxy_reset_timeouts(p);
926}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200928void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100930 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 defproxy.mode = PR_MODE_TCP;
932 defproxy.state = PR_STNEW;
933 defproxy.maxconn = cfg_maxpconn;
934 defproxy.conn_retries = CONN_RETRIES;
935 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100936
937 defproxy.defsrv.inter = DEF_CHKINTR;
938 defproxy.defsrv.fastinter = 0;
939 defproxy.defsrv.downinter = 0;
940 defproxy.defsrv.rise = DEF_RISETIME;
941 defproxy.defsrv.fall = DEF_FALLTIME;
942 defproxy.defsrv.check_port = 0;
943 defproxy.defsrv.maxqueue = 0;
944 defproxy.defsrv.minconn = 0;
945 defproxy.defsrv.maxconn = 0;
946 defproxy.defsrv.slowstart = 0;
947 defproxy.defsrv.onerror = DEF_HANA_ONERR;
948 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
949 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950}
951
Willy Tarreauade5ec42010-01-28 19:33:49 +0100952
953static int create_cond_regex_rule(const char *file, int line,
954 struct proxy *px, int dir, int action, int flags,
955 const char *cmd, const char *reg, const char *repl,
956 const char **cond_start)
957{
958 regex_t *preg = NULL;
959 const char *err;
960 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100961 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100962
963 if (px == &defproxy) {
964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto err;
967 }
968
969 if (*reg == 0) {
970 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto err;
973 }
974
975 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
976 err_code |= ERR_WARN;
977
Willy Tarreau5321c422010-01-28 20:35:13 +0100978 if (cond_start &&
979 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
980 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
981 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
982 file, line, cmd);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto err;
985 }
986 }
987 else if (cond_start && **cond_start) {
988 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
989 file, line, cmd, *cond_start);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto err;
992 }
993
994 if (dir == ACL_DIR_REQ)
995 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100996 else
997 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100998
Willy Tarreauade5ec42010-01-28 19:33:49 +0100999 preg = calloc(1, sizeof(regex_t));
1000 if (!preg) {
1001 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1002 err_code = ERR_ALERT | ERR_FATAL;
1003 goto err;
1004 }
1005
1006 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1007 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1008 err_code = ERR_ALERT | ERR_FATAL;
1009 goto err;
1010 }
1011
1012 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001013 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001014 if (repl && err) {
1015 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1016 file, line, cmd, *err);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto err;
1019 }
1020
1021 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1022 err_code |= ERR_WARN;
1023
1024 return err_code;
1025 err:
1026 free(preg);
1027 return err_code;
1028}
1029
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001031 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001032 * Returns the error code, 0 if OK, or any combination of :
1033 * - ERR_ABORT: must abort ASAP
1034 * - ERR_FATAL: we can continue parsing but not start the service
1035 * - ERR_WARN: a warning has been emitted
1036 * - ERR_ALERT: an alert has been emitted
1037 * Only the two first ones can stop processing, the two others are just
1038 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001040int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041{
1042 static struct proxy *curproxy = NULL;
1043 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001044 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001045 int rc;
1046 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001047 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001048 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049
Willy Tarreau977b8e42006-12-29 14:19:17 +01001050 if (!strcmp(args[0], "listen"))
1051 rc = PR_CAP_LISTEN;
1052 else if (!strcmp(args[0], "frontend"))
1053 rc = PR_CAP_FE | PR_CAP_RS;
1054 else if (!strcmp(args[0], "backend"))
1055 rc = PR_CAP_BE | PR_CAP_RS;
1056 else if (!strcmp(args[0], "ruleset"))
1057 rc = PR_CAP_RS;
1058 else
1059 rc = PR_CAP_NONE;
1060
1061 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 if (!*args[1]) {
1063 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1064 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1065 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001066 err_code |= ERR_ALERT | ERR_ABORT;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001069
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001070 err = invalid_char(args[1]);
1071 if (err) {
1072 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1073 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001075 }
1076
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001077 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1078 /*
1079 * If there are two proxies with the same name only following
1080 * combinations are allowed:
1081 *
1082 * listen backend frontend ruleset
1083 * listen - - - -
1084 * backend - - OK -
1085 * frontend - OK - -
1086 * ruleset - - - -
1087 */
1088
1089 if (!strcmp(curproxy->id, args[1]) &&
1090 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1091 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001092 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1093 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1094 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001095 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001096 }
1097 }
1098
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1100 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001101 err_code |= ERR_ALERT | ERR_ABORT;
1102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001104
Willy Tarreau97cb7802010-01-03 20:23:58 +01001105 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 curproxy->next = proxy;
1107 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001108 curproxy->conf.file = file;
1109 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001110 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001111 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001112 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113
1114 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001115 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001116 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001117 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001118 err_code |= ERR_FATAL;
1119 goto out;
1120 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001121 new = curproxy->listen;
1122 while (new != last) {
1123 new->conf.file = file;
1124 new->conf.line = linenum;
1125 new = new->next;
1126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 global.maxsock++;
1128 }
1129
1130 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001131 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001132 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001133
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001136 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001137 curproxy->no_options = defproxy.no_options;
1138 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001139 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001140 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001141 curproxy->except_net = defproxy.except_net;
1142 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001143 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001144 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001146 if (defproxy.fwdfor_hdr_len) {
1147 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1148 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1149 }
1150
Willy Tarreaub86db342009-11-30 11:50:16 +01001151 if (defproxy.orgto_hdr_len) {
1152 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1153 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1154 }
1155
Willy Tarreau977b8e42006-12-29 14:19:17 +01001156 if (curproxy->cap & PR_CAP_FE) {
1157 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001158 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001159 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001160
1161 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001162 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1163 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001164
1165 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167
Willy Tarreau977b8e42006-12-29 14:19:17 +01001168 if (curproxy->cap & PR_CAP_BE) {
1169 curproxy->fullconn = defproxy.fullconn;
1170 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001172 if (defproxy.check_req) {
1173 curproxy->check_req = calloc(1, defproxy.check_len);
1174 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1175 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001176 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177
Willy Tarreau977b8e42006-12-29 14:19:17 +01001178 if (defproxy.cookie_name)
1179 curproxy->cookie_name = strdup(defproxy.cookie_name);
1180 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001181 if (defproxy.cookie_domain)
1182 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001183
Willy Tarreau31936852010-10-06 16:59:56 +02001184 if (defproxy.cookie_maxidle)
1185 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1186
1187 if (defproxy.cookie_maxlife)
1188 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1189
Emeric Brun647caf12009-06-30 17:57:00 +02001190 if (defproxy.rdp_cookie_name)
1191 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1192 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1193
Willy Tarreau01732802007-11-01 22:48:15 +01001194 if (defproxy.url_param_name)
1195 curproxy->url_param_name = strdup(defproxy.url_param_name);
1196 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001197
Benoitaffb4812009-03-25 13:02:10 +01001198 if (defproxy.hh_name)
1199 curproxy->hh_name = strdup(defproxy.hh_name);
1200 curproxy->hh_len = defproxy.hh_len;
1201 curproxy->hh_match_domain = defproxy.hh_match_domain;
1202
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001203 if (defproxy.iface_name)
1204 curproxy->iface_name = strdup(defproxy.iface_name);
1205 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001208 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001209 if (defproxy.capture_name)
1210 curproxy->capture_name = strdup(defproxy.capture_name);
1211 curproxy->capture_namelen = defproxy.capture_namelen;
1212 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214
Willy Tarreau977b8e42006-12-29 14:19:17 +01001215 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001216 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001217 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001218 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001219 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001220 curproxy->uri_auth = defproxy.uri_auth;
1221 curproxy->mon_net = defproxy.mon_net;
1222 curproxy->mon_mask = defproxy.mon_mask;
1223 if (defproxy.monitor_uri)
1224 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1225 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001226 if (defproxy.defbe.name)
1227 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001228 }
1229
1230 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001231 curproxy->timeout.connect = defproxy.timeout.connect;
1232 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001233 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001234 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001235 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001236 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001237 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001238 curproxy->source_addr = defproxy.source_addr;
1239 }
1240
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 curproxy->mode = defproxy.mode;
1242 curproxy->logfac1 = defproxy.logfac1;
1243 curproxy->logsrv1 = defproxy.logsrv1;
1244 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001245 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 curproxy->logfac2 = defproxy.logfac2;
1247 curproxy->logsrv2 = defproxy.logsrv2;
1248 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001249 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001251 curproxy->conf.used_listener_id = EB_ROOT;
1252 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001253
Willy Tarreau93893792009-07-23 13:19:11 +02001254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 }
1256 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1257 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001258 /* FIXME-20070101: we should do this too at the end of the
1259 * config parsing to free all default values.
1260 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001261 free(defproxy.check_req);
1262 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001263 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001264 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001265 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001266 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001267 free(defproxy.capture_name);
1268 free(defproxy.monitor_uri);
1269 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001270 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001271 free(defproxy.fwdfor_hdr_name);
1272 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001273 free(defproxy.orgto_hdr_name);
1274 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001275
Willy Tarreaua534fea2008-08-03 12:19:50 +02001276 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001277 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001278
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 /* we cannot free uri_auth because it might already be used */
1280 init_default_instance();
1281 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001282 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
1285 else if (curproxy == NULL) {
1286 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 }
1290
Willy Tarreau977b8e42006-12-29 14:19:17 +01001291
1292 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001294 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001295 int cur_arg;
1296
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 if (curproxy == &defproxy) {
1298 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001302 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001303 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304
1305 if (strchr(args[1], ':') == NULL) {
1306 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001311
1312 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001313 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001314 err_code |= ERR_ALERT | ERR_FATAL;
1315 goto out;
1316 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001317
Willy Tarreau90a570f2009-10-04 20:54:54 +02001318 new_listen = curproxy->listen;
1319 while (new_listen != last_listen) {
1320 new_listen->conf.file = file;
1321 new_listen->conf.line = linenum;
1322 new_listen = new_listen->next;
1323 }
1324
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001325 cur_arg = 2;
1326 while (*(args[cur_arg])) {
1327 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1328#ifdef SO_BINDTODEVICE
1329 struct listener *l;
1330
1331 if (!*args[cur_arg + 1]) {
1332 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1333 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001336 }
1337
1338 for (l = curproxy->listen; l != last_listen; l = l->next)
1339 l->interface = strdup(args[cur_arg + 1]);
1340
1341 global.last_checks |= LSTCHK_NETADM;
1342
1343 cur_arg += 2;
1344 continue;
1345#else
1346 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1347 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001350#endif
1351 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001352 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1353#ifdef TCP_MAXSEG
1354 struct listener *l;
1355 int mss;
1356
1357 if (!*args[cur_arg + 1]) {
1358 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001362 }
1363
1364 mss = str2uic(args[cur_arg + 1]);
1365 if (mss < 1 || mss > 65535) {
1366 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1367 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001370 }
1371
1372 for (l = curproxy->listen; l != last_listen; l = l->next)
1373 l->maxseg = mss;
1374
1375 cur_arg += 2;
1376 continue;
1377#else
1378 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1379 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001382#endif
1383 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001384
1385 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1386#ifdef TCP_DEFER_ACCEPT
1387 struct listener *l;
1388
1389 for (l = curproxy->listen; l != last_listen; l = l->next)
1390 l->options |= LI_O_DEF_ACCEPT;
1391
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]);
1397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
1399#endif
1400 }
1401
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001402 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001403#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001404 struct listener *l;
1405
1406 for (l = curproxy->listen; l != last_listen; l = l->next)
1407 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001408
1409 cur_arg ++;
1410 continue;
1411#else
1412 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1413 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001416#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001417 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001418
1419 if (!strcmp(args[cur_arg], "name")) {
1420 struct listener *l;
1421
1422 for (l = curproxy->listen; l != last_listen; l = l->next)
1423 l->name = strdup(args[cur_arg + 1]);
1424
1425 cur_arg += 2;
1426 continue;
1427 }
1428
1429 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001430 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001431 struct listener *l;
1432
1433 if (curproxy->listen->next != last_listen) {
1434 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1435 file, linenum, args[cur_arg]);
1436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
1438 }
1439
1440 if (!*args[cur_arg + 1]) {
1441 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1442 file, linenum, args[cur_arg]);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446
1447 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001448 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001449
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001450 if (curproxy->listen->luid <= 0) {
1451 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001452 file, linenum);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto out;
1455 }
1456
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001457 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1458 if (node) {
1459 l = container_of(node, struct listener, conf.id);
1460 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1461 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1462 err_code |= ERR_ALERT | ERR_FATAL;
1463 goto out;
1464 }
1465 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1466
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001467 cur_arg += 2;
1468 continue;
1469 }
1470
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001471 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 +01001472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478 }
1479 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1480 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1481 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001487 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001488
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 /* flush useless bits */
1490 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001493 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001495 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001496
Willy Tarreau1c47f852006-07-09 08:22:27 +02001497 if (!*args[1]) {
1498 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1499 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001500 err_code |= ERR_ALERT | ERR_FATAL;
1501 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001502 }
1503
Willy Tarreaua534fea2008-08-03 12:19:50 +02001504 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001505 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001506 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001507 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001508 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1509
Willy Tarreau93893792009-07-23 13:19:11 +02001510 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1513 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1514 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1515 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1516 else {
1517 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 }
1521 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001522 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001523 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001524
1525 if (curproxy == &defproxy) {
1526 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1527 file, linenum, args[0]);
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
1532 if (!*args[1]) {
1533 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1534 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001535 err_code |= ERR_ALERT | ERR_FATAL;
1536 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001537 }
1538
1539 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001540 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001541
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001542 if (curproxy->uuid <= 0) {
1543 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001544 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001547 }
1548
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001549 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1550 if (node) {
1551 struct proxy *target = container_of(node, struct proxy, conf.id);
1552 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1553 file, linenum, proxy_type_str(curproxy), curproxy->id,
1554 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557 }
1558 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001559 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001560 else if (!strcmp(args[0], "description")) {
1561 int i, len=0;
1562 char *d;
1563
Cyril Bonté99ed3272010-01-24 23:29:44 +01001564 if (curproxy == &defproxy) {
1565 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1566 file, linenum, args[0]);
1567 err_code |= ERR_ALERT | ERR_FATAL;
1568 goto out;
1569 }
1570
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001571 if (!*args[1]) {
1572 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1573 file, linenum, args[0]);
1574 return -1;
1575 }
1576
1577 for(i=1; *args[i]; i++)
1578 len += strlen(args[i])+1;
1579
1580 d = (char *)calloc(1, len);
1581 curproxy->desc = d;
1582
1583 d += sprintf(d, "%s", args[1]);
1584 for(i=2; *args[i]; i++)
1585 d += sprintf(d, " %s", args[i]);
1586
1587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1589 curproxy->state = PR_STSTOPPED;
1590 }
1591 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1592 curproxy->state = PR_STNEW;
1593 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001594 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1595 int cur_arg = 1;
1596 unsigned int set = 0;
1597
1598 while (*args[cur_arg]) {
1599 int u;
1600 if (strcmp(args[cur_arg], "all") == 0) {
1601 set = 0;
1602 break;
1603 }
1604 else if (strcmp(args[cur_arg], "odd") == 0) {
1605 set |= 0x55555555;
1606 }
1607 else if (strcmp(args[cur_arg], "even") == 0) {
1608 set |= 0xAAAAAAAA;
1609 }
1610 else {
1611 u = str2uic(args[cur_arg]);
1612 if (u < 1 || u > 32) {
1613 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1614 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001617 }
1618 if (u > global.nbproc) {
1619 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001621 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001622 }
1623 set |= 1 << (u - 1);
1624 }
1625 cur_arg++;
1626 }
1627 curproxy->bind_proc = set;
1628 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001629 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001630 if (curproxy == &defproxy) {
1631 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_ALERT | ERR_FATAL;
1633 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001634 }
1635
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001636 err = invalid_char(args[1]);
1637 if (err) {
1638 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1639 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001640 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001641 }
1642
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001643 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1644 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1645 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001646 err_code |= ERR_ALERT | ERR_FATAL;
1647 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001648 }
1649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1651 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652
Willy Tarreau977b8e42006-12-29 14:19:17 +01001653 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001654 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001655
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 if (*(args[1]) == 0) {
1657 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001662
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001663 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001664 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001665 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001666 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001667 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668 curproxy->cookie_name = strdup(args[1]);
1669 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001670
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 cur_arg = 2;
1672 while (*(args[cur_arg])) {
1673 if (!strcmp(args[cur_arg], "rewrite")) {
1674 curproxy->options |= PR_O_COOK_RW;
1675 }
1676 else if (!strcmp(args[cur_arg], "indirect")) {
1677 curproxy->options |= PR_O_COOK_IND;
1678 }
1679 else if (!strcmp(args[cur_arg], "insert")) {
1680 curproxy->options |= PR_O_COOK_INS;
1681 }
1682 else if (!strcmp(args[cur_arg], "nocache")) {
1683 curproxy->options |= PR_O_COOK_NOC;
1684 }
1685 else if (!strcmp(args[cur_arg], "postonly")) {
1686 curproxy->options |= PR_O_COOK_POST;
1687 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001688 else if (!strcmp(args[cur_arg], "preserve")) {
1689 curproxy->options2 |= PR_O2_COOK_PSV;
1690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 else if (!strcmp(args[cur_arg], "prefix")) {
1692 curproxy->options |= PR_O_COOK_PFX;
1693 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001694 else if (!strcmp(args[cur_arg], "domain")) {
1695 if (!*args[cur_arg + 1]) {
1696 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1697 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001698 err_code |= ERR_ALERT | ERR_FATAL;
1699 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001700 }
1701
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001702 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001703 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001704 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1705 " dots nor does not start with a dot."
1706 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001707 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001708 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001709 }
1710
1711 err = invalid_domainchar(args[cur_arg + 1]);
1712 if (err) {
1713 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1714 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001717 }
1718
Willy Tarreau68a897b2009-12-03 23:28:34 +01001719 if (!curproxy->cookie_domain) {
1720 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1721 } else {
1722 /* one domain was already specified, add another one by
1723 * building the string which will be returned along with
1724 * the cookie.
1725 */
1726 char *new_ptr;
1727 int new_len = strlen(curproxy->cookie_domain) +
1728 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1729 new_ptr = malloc(new_len);
1730 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1731 free(curproxy->cookie_domain);
1732 curproxy->cookie_domain = new_ptr;
1733 }
Willy Tarreau31936852010-10-06 16:59:56 +02001734 cur_arg++;
1735 }
1736 else if (!strcmp(args[cur_arg], "maxidle")) {
1737 unsigned int maxidle;
1738 const char *res;
1739
1740 if (!*args[cur_arg + 1]) {
1741 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
1742 file, linenum, args[cur_arg]);
1743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
1745 }
1746
1747 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
1748 if (res) {
1749 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
1750 file, linenum, *res, args[cur_arg]);
1751 err_code |= ERR_ALERT | ERR_FATAL;
1752 goto out;
1753 }
1754 curproxy->cookie_maxidle = maxidle;
1755 cur_arg++;
1756 }
1757 else if (!strcmp(args[cur_arg], "maxlife")) {
1758 unsigned int maxlife;
1759 const char *res;
1760
1761 if (!*args[cur_arg + 1]) {
1762 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
1763 file, linenum, args[cur_arg]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767
1768 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
1769 if (res) {
1770 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
1771 file, linenum, *res, args[cur_arg]);
1772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
1774 }
1775 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001776 cur_arg++;
1777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 else {
Willy Tarreau31936852010-10-06 16:59:56 +02001779 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 }
1784 cur_arg++;
1785 }
1786 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1787 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1788 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 }
1791
1792 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1793 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1794 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001797
1798 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
1799 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
1800 file, linenum);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001804 else if (!strcmp(args[0], "persist")) { /* persist */
1805 if (*(args[1]) == 0) {
1806 Alert("parsing [%s:%d] : missing persist method.\n",
1807 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001810 }
1811
1812 if (!strncmp(args[1], "rdp-cookie", 10)) {
1813 curproxy->options2 |= PR_O2_RDPC_PRST;
1814
Emeric Brunb982a3d2010-01-04 15:45:53 +01001815 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001816 const char *beg, *end;
1817
1818 beg = args[1] + 11;
1819 end = strchr(beg, ')');
1820
1821 if (!end || end == beg) {
1822 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1823 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001826 }
1827
1828 free(curproxy->rdp_cookie_name);
1829 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1830 curproxy->rdp_cookie_len = end-beg;
1831 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001832 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001833 free(curproxy->rdp_cookie_name);
1834 curproxy->rdp_cookie_name = strdup("msts");
1835 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1836 }
1837 else { /* syntax */
1838 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1839 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001842 }
1843 }
1844 else {
1845 Alert("parsing [%s:%d] : unknown persist method.\n",
1846 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001849 }
1850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001851 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001852 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001854 if (curproxy == &defproxy) {
1855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1856 err_code |= ERR_ALERT | ERR_FATAL;
1857 goto out;
1858 }
1859
Willy Tarreau977b8e42006-12-29 14:19:17 +01001860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001862
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001864 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 }
1869 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001870 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->appsession_name = strdup(args[1]);
1872 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1873 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001874 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1875 if (err) {
1876 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1877 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001880 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001881 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001882
Willy Tarreau51041c72007-09-09 21:56:53 +02001883 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1884 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001885 err_code |= ERR_ALERT | ERR_ABORT;
1886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001888
1889 cur_arg = 6;
1890 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001891 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1892 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001893 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001894 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001895 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001896 } else if (!strcmp(args[cur_arg], "prefix")) {
1897 curproxy->options2 |= PR_O2_AS_PFX;
1898 } else if (!strcmp(args[cur_arg], "mode")) {
1899 if (!*args[cur_arg + 1]) {
1900 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1901 file, linenum, args[0], args[cur_arg]);
1902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
1904 }
1905
1906 cur_arg++;
1907 if (!strcmp(args[cur_arg], "query-string")) {
1908 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1909 curproxy->options2 |= PR_O2_AS_M_QS;
1910 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1911 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1912 curproxy->options2 |= PR_O2_AS_M_PP;
1913 } else {
1914 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
1917 }
1918 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001919 cur_arg++;
1920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 } /* Url App Session */
1922 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001923 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001927 if (curproxy == &defproxy) {
1928 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
1931 }
1932
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 if (*(args[4]) == 0) {
1934 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1935 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001939 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 curproxy->capture_name = strdup(args[2]);
1941 curproxy->capture_namelen = strlen(curproxy->capture_name);
1942 curproxy->capture_len = atol(args[4]);
1943 if (curproxy->capture_len >= CAPTURE_LEN) {
1944 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1945 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 curproxy->capture_len = CAPTURE_LEN - 1;
1948 }
1949 curproxy->to_log |= LW_COOKIE;
1950 }
1951 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1952 struct cap_hdr *hdr;
1953
1954 if (curproxy == &defproxy) {
1955 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 +02001956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 }
1959
1960 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1961 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1962 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 }
1966
1967 hdr = calloc(sizeof(struct cap_hdr), 1);
1968 hdr->next = curproxy->req_cap;
1969 hdr->name = strdup(args[3]);
1970 hdr->namelen = strlen(args[3]);
1971 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001972 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 hdr->index = curproxy->nb_req_cap++;
1974 curproxy->req_cap = hdr;
1975 curproxy->to_log |= LW_REQHDR;
1976 }
1977 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1978 struct cap_hdr *hdr;
1979
1980 if (curproxy == &defproxy) {
1981 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 +02001982 err_code |= ERR_ALERT | ERR_FATAL;
1983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 }
1985
1986 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1987 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1988 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 }
1992 hdr = calloc(sizeof(struct cap_hdr), 1);
1993 hdr->next = curproxy->rsp_cap;
1994 hdr->name = strdup(args[3]);
1995 hdr->namelen = strlen(args[3]);
1996 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001997 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 hdr->index = curproxy->nb_rsp_cap++;
1999 curproxy->rsp_cap = hdr;
2000 curproxy->to_log |= LW_RSPHDR;
2001 }
2002 else {
2003 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2004 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002005 err_code |= ERR_ALERT | ERR_FATAL;
2006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 }
2008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002010 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002012
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 if (*(args[1]) == 0) {
2014 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 }
2019 curproxy->conn_retries = atol(args[1]);
2020 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002021 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2022 struct req_acl_rule *req_acl;
2023
2024 if (curproxy == &defproxy) {
2025 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
2028 }
2029
2030
2031 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2032 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2033 file, linenum, args[0]);
2034 err_code |= ERR_WARN;
2035 }
2036
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002037 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002038
2039 if (!req_acl) {
2040 err_code |= ERR_ALERT | ERR_ABORT;
2041 goto out;
2042 }
2043
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002044 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002045 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2046 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002047 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002048 if (curproxy == &defproxy) {
2049 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002052 }
2053
Willy Tarreauef6494c2010-01-28 17:12:36 +01002054 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002055 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2056 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002059 }
2060
Willy Tarreauef6494c2010-01-28 17:12:36 +01002061 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002062 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2063 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002066 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002067
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002068 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002069 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002070 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002071 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002072 struct redirect_rule *rule;
2073 int cur_arg;
2074 int type = REDIRECT_TYPE_NONE;
2075 int code = 302;
2076 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002077 char *cookie = NULL;
2078 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002079 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002080
Cyril Bonté99ed3272010-01-24 23:29:44 +01002081 if (curproxy == &defproxy) {
2082 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
2085 }
2086
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002087 cur_arg = 1;
2088 while (*(args[cur_arg])) {
2089 if (!strcmp(args[cur_arg], "location")) {
2090 if (!*args[cur_arg + 1]) {
2091 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2092 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002095 }
2096
2097 type = REDIRECT_TYPE_LOCATION;
2098 cur_arg++;
2099 destination = args[cur_arg];
2100 }
2101 else if (!strcmp(args[cur_arg], "prefix")) {
2102 if (!*args[cur_arg + 1]) {
2103 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2104 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002107 }
2108
2109 type = REDIRECT_TYPE_PREFIX;
2110 cur_arg++;
2111 destination = args[cur_arg];
2112 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002113 else if (!strcmp(args[cur_arg], "set-cookie")) {
2114 if (!*args[cur_arg + 1]) {
2115 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2116 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002119 }
2120
2121 cur_arg++;
2122 cookie = args[cur_arg];
2123 cookie_set = 1;
2124 }
2125 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2126 if (!*args[cur_arg + 1]) {
2127 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2128 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002131 }
2132
2133 cur_arg++;
2134 cookie = args[cur_arg];
2135 cookie_set = 0;
2136 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002137 else if (!strcmp(args[cur_arg],"code")) {
2138 if (!*args[cur_arg + 1]) {
2139 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002143 }
2144 cur_arg++;
2145 code = atol(args[cur_arg]);
2146 if (code < 301 || code > 303) {
2147 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2148 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002151 }
2152 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002153 else if (!strcmp(args[cur_arg],"drop-query")) {
2154 flags |= REDIRECT_FLAG_DROP_QS;
2155 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002156 else if (!strcmp(args[cur_arg],"append-slash")) {
2157 flags |= REDIRECT_FLAG_APPEND_SLASH;
2158 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002159 else if (strcmp(args[cur_arg], "if") == 0 ||
2160 strcmp(args[cur_arg], "unless") == 0) {
2161 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2162 if (!cond) {
2163 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2164 file, linenum, args[0]);
2165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002168 break;
2169 }
2170 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002171 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 +02002172 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002173 err_code |= ERR_ALERT | ERR_FATAL;
2174 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002175 }
2176 cur_arg++;
2177 }
2178
2179 if (type == REDIRECT_TYPE_NONE) {
2180 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002184 }
2185
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002186 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2187 rule->cond = cond;
2188 rule->rdr_str = strdup(destination);
2189 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002190 if (cookie) {
2191 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002192 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002193 */
2194 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002195 if (cookie_set) {
2196 rule->cookie_str = malloc(rule->cookie_len + 10);
2197 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2198 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2199 rule->cookie_len += 9;
2200 } else {
2201 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002202 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002203 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2204 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002205 }
2206 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002207 rule->type = type;
2208 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002209 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002210 LIST_INIT(&rule->list);
2211 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002212 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002213 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002214 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002215 struct switching_rule *rule;
2216
Willy Tarreaub099aca2008-10-12 17:26:37 +02002217 if (curproxy == &defproxy) {
2218 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002221 }
2222
Willy Tarreau55ea7572007-06-17 19:56:27 +02002223 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002225
2226 if (*(args[1]) == 0) {
2227 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002230 }
2231
Willy Tarreauef6494c2010-01-28 17:12:36 +01002232 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002233 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002237 }
2238
Willy Tarreauef6494c2010-01-28 17:12:36 +01002239 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002240 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002241 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002244 }
2245
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002246 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002247
Willy Tarreau55ea7572007-06-17 19:56:27 +02002248 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2249 rule->cond = cond;
2250 rule->be.name = strdup(args[1]);
2251 LIST_INIT(&rule->list);
2252 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2253 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002254 else if ((!strcmp(args[0], "force-persist")) ||
2255 (!strcmp(args[0], "ignore-persist"))) {
2256 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002257
2258 if (curproxy == &defproxy) {
2259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263
2264 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2265 err_code |= ERR_WARN;
2266
Willy Tarreauef6494c2010-01-28 17:12:36 +01002267 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002268 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2269 file, linenum, args[0]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
2273
Willy Tarreauef6494c2010-01-28 17:12:36 +01002274 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002275 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2276 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002281 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002282
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002283 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002284 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002285 if (!strcmp(args[0], "force-persist")) {
2286 rule->type = PERSIST_TYPE_FORCE;
2287 } else {
2288 rule->type = PERSIST_TYPE_IGNORE;
2289 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002290 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002291 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002292 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002293 else if (!strcmp(args[0], "stick-table")) {
2294 int myidx = 1;
2295
2296 curproxy->table.type = (unsigned int)-1;
2297 while (*args[myidx]) {
2298 const char *err;
2299
2300 if (strcmp(args[myidx], "size") == 0) {
2301 myidx++;
2302 if (!*(args[myidx])) {
2303 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2304 file, linenum, args[myidx-1]);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2309 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2310 file, linenum, *err, args[myidx-1]);
2311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
2313 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002314 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002315 }
2316 else if (strcmp(args[myidx], "expire") == 0) {
2317 myidx++;
2318 if (!*(args[myidx])) {
2319 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2320 file, linenum, args[myidx-1]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2325 if (err) {
2326 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2327 file, linenum, *err, args[myidx-1]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002332 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002333 }
2334 else if (strcmp(args[myidx], "nopurge") == 0) {
2335 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002336 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002337 }
2338 else if (strcmp(args[myidx], "type") == 0) {
2339 myidx++;
2340 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2341 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2342 file, linenum, args[myidx]);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002346 /* myidx already points to next arg */
2347 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002348 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002349 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002350 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002351
2352 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002353 nw = args[myidx];
2354 while (*nw) {
2355 /* the "store" keyword supports a comma-separated list */
2356 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002357 sa = NULL; /* store arg */
2358 while (*nw && *nw != ',') {
2359 if (*nw == '(') {
2360 *nw = 0;
2361 sa = ++nw;
2362 while (*nw != ')') {
2363 if (!*nw) {
2364 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2365 file, linenum, args[0], cw);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369 nw++;
2370 }
2371 *nw = '\0';
2372 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002373 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002374 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002375 if (*nw)
2376 *nw++ = '\0';
2377 type = stktable_get_data_type(cw);
2378 if (type < 0) {
2379 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2380 file, linenum, args[0], cw);
2381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
2383 }
Willy Tarreauac782882010-06-20 10:41:54 +02002384
2385 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2386 switch (err) {
2387 case PE_NONE: break;
2388 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002389 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2390 file, linenum, args[0], cw);
2391 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002392 break;
2393
2394 case PE_ARG_MISSING:
2395 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2396 file, linenum, args[0], cw);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399
2400 case PE_ARG_NOT_USED:
2401 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2402 file, linenum, args[0], cw);
2403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
2405
2406 default:
2407 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2408 file, linenum, args[0], cw);
2409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002411 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002412 }
2413 myidx++;
2414 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002415 else {
2416 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2417 file, linenum, args[myidx]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002420 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002421 }
2422
2423 if (!curproxy->table.size) {
2424 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2425 file, linenum);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 if (curproxy->table.type == (unsigned int)-1) {
2431 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2432 file, linenum);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
2435 }
2436 }
2437 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002438 struct sticking_rule *rule;
2439 struct pattern_expr *expr;
2440 int myidx = 0;
2441 const char *name = NULL;
2442 int flags;
2443
2444 if (curproxy == &defproxy) {
2445 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
2450 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2451 err_code |= ERR_WARN;
2452 goto out;
2453 }
2454
2455 myidx++;
2456 if ((strcmp(args[myidx], "store") == 0) ||
2457 (strcmp(args[myidx], "store-request") == 0)) {
2458 myidx++;
2459 flags = STK_IS_STORE;
2460 }
2461 else if (strcmp(args[myidx], "store-response") == 0) {
2462 myidx++;
2463 flags = STK_IS_STORE | STK_ON_RSP;
2464 }
2465 else if (strcmp(args[myidx], "match") == 0) {
2466 myidx++;
2467 flags = STK_IS_MATCH;
2468 }
2469 else if (strcmp(args[myidx], "on") == 0) {
2470 myidx++;
2471 flags = STK_IS_MATCH | STK_IS_STORE;
2472 }
2473 else {
2474 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 if (*(args[myidx]) == 0) {
2480 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484
2485 expr = pattern_parse_expr(args, &myidx);
2486 if (!expr) {
2487 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491
2492 if (flags & STK_ON_RSP) {
2493 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2494 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2495 file, linenum, args[0], expr->fetch->kw);
2496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
2498 }
2499 } else {
2500 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2501 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2502 file, linenum, args[0], expr->fetch->kw);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506 }
2507
2508 if (strcmp(args[myidx], "table") == 0) {
2509 myidx++;
2510 name = args[myidx++];
2511 }
2512
Willy Tarreauef6494c2010-01-28 17:12:36 +01002513 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2514 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002515 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2516 file, linenum, args[0]);
2517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
2519 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002520 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002521 else if (*(args[myidx])) {
2522 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2523 file, linenum, args[0], args[myidx]);
2524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
2526 }
2527
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002528 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2529
Emeric Brunb982a3d2010-01-04 15:45:53 +01002530 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2531 rule->cond = cond;
2532 rule->expr = expr;
2533 rule->flags = flags;
2534 rule->table.name = name ? strdup(name) : NULL;
2535 LIST_INIT(&rule->list);
2536 if (flags & STK_ON_RSP)
2537 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2538 else
2539 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002542 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2546 curproxy->uri_auth = NULL; /* we must detach from the default config */
2547
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002548 if (!*args[1]) {
2549 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002550 } else if (!strcmp(args[1], "admin")) {
2551 struct stats_admin_rule *rule;
2552
2553 if (curproxy == &defproxy) {
2554 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
2557 }
2558
2559 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2560 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2561 err_code |= ERR_ALERT | ERR_ABORT;
2562 goto out;
2563 }
2564
2565 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2566 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2567 file, linenum, args[0], args[1]);
2568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
2570 }
2571 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2572 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2573 file, linenum, args[0], args[1]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577
2578 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2579
2580 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2581 rule->cond = cond;
2582 LIST_INIT(&rule->list);
2583 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 } else if (!strcmp(args[1], "uri")) {
2585 if (*(args[2]) == 0) {
2586 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2590 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_ABORT;
2592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 }
2594 } else if (!strcmp(args[1], "realm")) {
2595 if (*(args[2]) == 0) {
2596 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2600 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_ALERT | ERR_ABORT;
2602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002604 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002605 unsigned interval;
2606
2607 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2608 if (err) {
2609 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2610 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002613 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2614 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_ABORT;
2616 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002617 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002618 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2619 struct req_acl_rule *req_acl;
2620
2621 if (curproxy == &defproxy) {
2622 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
2625 }
2626
2627 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2628 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2629 err_code |= ERR_ALERT | ERR_ABORT;
2630 goto out;
2631 }
2632
2633 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2634 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2635 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2636 file, linenum, args[0]);
2637 err_code |= ERR_WARN;
2638 }
2639
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002640 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002641
2642 if (!req_acl) {
2643 err_code |= ERR_ALERT | ERR_ABORT;
2644 goto out;
2645 }
2646
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002647 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002648 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2649
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 } else if (!strcmp(args[1], "auth")) {
2651 if (*(args[2]) == 0) {
2652 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
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 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2656 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_ABORT;
2658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659 }
2660 } else if (!strcmp(args[1], "scope")) {
2661 if (*(args[2]) == 0) {
2662 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2666 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_ABORT;
2668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 }
2670 } else if (!strcmp(args[1], "enable")) {
2671 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2672 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002673 err_code |= ERR_ALERT | ERR_ABORT;
2674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002676 } else if (!strcmp(args[1], "hide-version")) {
2677 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2678 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_ABORT;
2680 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002681 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002682 } else if (!strcmp(args[1], "show-legends")) {
2683 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2684 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2685 err_code |= ERR_ALERT | ERR_ABORT;
2686 goto out;
2687 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002688 } else if (!strcmp(args[1], "show-node")) {
2689
2690 if (*args[2]) {
2691 int i;
2692 char c;
2693
2694 for (i=0; args[2][i]; i++) {
2695 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002696 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2697 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002698 break;
2699 }
2700
2701 if (!i || args[2][i]) {
2702 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2703 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2704 file, linenum, args[0], args[1]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708 }
2709
2710 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2711 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2712 err_code |= ERR_ALERT | ERR_ABORT;
2713 goto out;
2714 }
2715 } else if (!strcmp(args[1], "show-desc")) {
2716 char *desc = NULL;
2717
2718 if (*args[2]) {
2719 int i, len=0;
2720 char *d;
2721
2722 for(i=2; *args[i]; i++)
2723 len += strlen(args[i])+1;
2724
2725 desc = d = (char *)calloc(1, len);
2726
2727 d += sprintf(d, "%s", args[2]);
2728 for(i=3; *args[i]; i++)
2729 d += sprintf(d, " %s", args[i]);
2730 }
2731
2732 if (!*args[2] && !global.desc)
2733 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2734 file, linenum, args[1]);
2735 else {
2736 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2737 free(desc);
2738 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2739 err_code |= ERR_ALERT | ERR_ABORT;
2740 goto out;
2741 }
2742 free(desc);
2743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002744 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002745stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02002746 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002747 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 }
2751 }
2752 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002753 int optnum;
2754
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002755 if (*(args[1]) == '\0') {
2756 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2757 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002761
2762 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2763 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002764 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2765 err_code |= ERR_WARN;
2766 goto out;
2767 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002768
Willy Tarreau3842f002009-06-14 11:39:52 +02002769 curproxy->no_options &= ~cfg_opts[optnum].val;
2770 curproxy->options &= ~cfg_opts[optnum].val;
2771
2772 switch (kwm) {
2773 case KWM_STD:
2774 curproxy->options |= cfg_opts[optnum].val;
2775 break;
2776 case KWM_NO:
2777 curproxy->no_options |= cfg_opts[optnum].val;
2778 break;
2779 case KWM_DEF: /* already cleared */
2780 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002781 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002782
Willy Tarreau93893792009-07-23 13:19:11 +02002783 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002784 }
2785 }
2786
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002787 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2788 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002789 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2790 err_code |= ERR_WARN;
2791 goto out;
2792 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002793
Willy Tarreau3842f002009-06-14 11:39:52 +02002794 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2795 curproxy->options2 &= ~cfg_opts2[optnum].val;
2796
2797 switch (kwm) {
2798 case KWM_STD:
2799 curproxy->options2 |= cfg_opts2[optnum].val;
2800 break;
2801 case KWM_NO:
2802 curproxy->no_options2 |= cfg_opts2[optnum].val;
2803 break;
2804 case KWM_DEF: /* already cleared */
2805 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002806 }
Willy Tarreau93893792009-07-23 13:19:11 +02002807 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002808 }
2809 }
2810
Willy Tarreau3842f002009-06-14 11:39:52 +02002811 if (kwm != KWM_STD) {
2812 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002813 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002816 }
2817
Emeric Brun3a058f32009-06-30 18:26:00 +02002818 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002820 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002822 if (*(args[2]) != '\0') {
2823 if (!strcmp(args[2], "clf")) {
2824 curproxy->options2 |= PR_O2_CLFLOG;
2825 } else {
2826 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002829 }
2830 }
2831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 else if (!strcmp(args[1], "tcplog"))
2833 /* generate a detailed TCP log */
2834 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 else if (!strcmp(args[1], "tcpka")) {
2836 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002837 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002839
2840 if (curproxy->cap & PR_CAP_FE)
2841 curproxy->options |= PR_O_TCP_CLI_KA;
2842 if (curproxy->cap & PR_CAP_BE)
2843 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 }
2845 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002846 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002847 err_code |= ERR_WARN;
2848
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002850 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002851 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002852 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002853 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002854 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002855 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002856 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 if (!*args[2]) { /* no argument */
2858 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2859 curproxy->check_len = strlen(DEF_CHECK_REQ);
2860 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002861 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 curproxy->check_req = (char *)malloc(reqlen);
2863 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002864 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002866 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 if (*args[4])
2868 reqlen += strlen(args[4]);
2869 else
2870 reqlen += strlen("HTTP/1.0");
2871
2872 curproxy->check_req = (char *)malloc(reqlen);
2873 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002874 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002876 }
2877 else if (!strcmp(args[1], "ssl-hello-chk")) {
2878 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002879 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002881
Willy Tarreaua534fea2008-08-03 12:19:50 +02002882 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002883 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002884 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002885 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002886 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002887 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002888 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }
Willy Tarreau23677902007-05-08 23:50:35 +02002890 else if (!strcmp(args[1], "smtpchk")) {
2891 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002892 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002893 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002894 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002895 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002896 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002897 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002898 curproxy->options |= PR_O_SMTP_CHK;
2899
2900 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2901 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2902 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2903 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2904 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2905 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2906 curproxy->check_req = (char *)malloc(reqlen);
2907 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2908 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2909 } else {
2910 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2911 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2912 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2913 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2914 }
2915 }
2916 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002917 else if (!strcmp(args[1], "mysql-check")) {
2918 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02002919 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2920 err_code |= ERR_WARN;
2921
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002922 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002923 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002924 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002925 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002926 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002927 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002928 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02002929
2930 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
2931 * const char mysql40_client_auth_pkt[] = {
2932 * "\x0e\x00\x00" // packet length
2933 * "\x01" // packet number
2934 * "\x00\x00" // client capabilities
2935 * "\x00\x00\x01" // max packet
2936 * "haproxy\x00" // username (null terminated string)
2937 * "\x00" // filler (always 0x00)
2938 * "\x01\x00\x00" // packet length
2939 * "\x00" // packet number
2940 * "\x01" // COM_QUIT command
2941 * };
2942 */
2943
2944 if (*(args[2])) {
2945 int cur_arg = 2;
2946
2947 while (*(args[cur_arg])) {
2948 if (strcmp(args[cur_arg], "user") == 0) {
2949 char *mysqluser;
2950 int packetlen, reqlen, userlen;
2951
2952 /* suboption header - needs additional argument for it */
2953 if (*(args[cur_arg+1]) == 0) {
2954 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
2955 file, linenum, args[0], args[1], args[cur_arg]);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959 mysqluser = args[cur_arg + 1];
2960 userlen = strlen(mysqluser);
2961 packetlen = userlen + 7;
2962 reqlen = packetlen + 9;
2963
2964 free(curproxy->check_req);
2965 curproxy->check_req = (char *)calloc(1, reqlen);
2966 curproxy->check_len = reqlen;
2967
2968 snprintf(curproxy->check_req, 4, "%c%c%c",
2969 ((unsigned char) packetlen & 0xff),
2970 ((unsigned char) (packetlen >> 8) & 0xff),
2971 ((unsigned char) (packetlen >> 16) & 0xff));
2972
2973 curproxy->check_req[3] = 1;
2974 curproxy->check_req[8] = 1;
2975 memcpy(&curproxy->check_req[9], mysqluser, userlen);
2976 curproxy->check_req[9 + userlen + 1 + 1] = 1;
2977 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
2978 cur_arg += 2;
2979 } else {
2980 /* unknown suboption - catchall */
2981 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
2982 file, linenum, args[0], args[1]);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986 } /* end while loop */
2987 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002988 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002989 else if (!strcmp(args[1], "ldap-check")) {
2990 /* use LDAP request to check servers' health */
2991 free(curproxy->check_req);
2992 curproxy->check_req = NULL;
2993 curproxy->options &= ~PR_O_HTTP_CHK;
2994 curproxy->options &= ~PR_O_SMTP_CHK;
2995 curproxy->options2 &= ~PR_O2_SSL3_CHK;
2996 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
2997 curproxy->options2 |= PR_O2_LDAP_CHK;
2998
2999 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3000 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3001 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3002 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003003 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003004 int cur_arg;
3005
3006 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3007 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003008 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003009
3010 curproxy->options |= PR_O_FWDFOR;
3011
3012 free(curproxy->fwdfor_hdr_name);
3013 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3014 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3015
3016 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3017 cur_arg = 2;
3018 while (*(args[cur_arg])) {
3019 if (!strcmp(args[cur_arg], "except")) {
3020 /* suboption except - needs additional argument for it */
3021 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3022 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3023 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003026 }
3027 /* flush useless bits */
3028 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003029 cur_arg += 2;
3030 } else if (!strcmp(args[cur_arg], "header")) {
3031 /* suboption header - needs additional argument for it */
3032 if (*(args[cur_arg+1]) == 0) {
3033 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3034 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003037 }
3038 free(curproxy->fwdfor_hdr_name);
3039 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3040 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3041 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003042 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003043 /* unknown suboption - catchall */
3044 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3045 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003048 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003049 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003050 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003051 else if (!strcmp(args[1], "originalto")) {
3052 int cur_arg;
3053
3054 /* insert x-original-to field, but not for the IP address listed as an except.
3055 * set default options (ie: bitfield, header name, etc)
3056 */
3057
3058 curproxy->options |= PR_O_ORGTO;
3059
3060 free(curproxy->orgto_hdr_name);
3061 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3062 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3063
3064 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3065 cur_arg = 2;
3066 while (*(args[cur_arg])) {
3067 if (!strcmp(args[cur_arg], "except")) {
3068 /* suboption except - needs additional argument for it */
3069 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3070 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3071 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003074 }
3075 /* flush useless bits */
3076 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3077 cur_arg += 2;
3078 } else if (!strcmp(args[cur_arg], "header")) {
3079 /* suboption header - needs additional argument for it */
3080 if (*(args[cur_arg+1]) == 0) {
3081 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3082 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003085 }
3086 free(curproxy->orgto_hdr_name);
3087 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3088 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3089 cur_arg += 2;
3090 } else {
3091 /* unknown suboption - catchall */
3092 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3093 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003096 }
3097 } /* end while loop */
3098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 else {
3100 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
Willy Tarreau93893792009-07-23 13:19:11 +02003104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003106 else if (!strcmp(args[0], "default_backend")) {
3107 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003109
3110 if (*(args[1]) == 0) {
3111 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003114 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003115 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003116 curproxy->defbe.name = strdup(args[1]);
3117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003119 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003121
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003122 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 /* enable reconnections to dispatch */
3126 curproxy->options |= PR_O_REDISP;
3127 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003128 else if (!strcmp(args[0], "http-check")) {
3129 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003131
3132 if (strcmp(args[1], "disable-on-404") == 0) {
3133 /* enable a graceful server shutdown on an HTTP 404 response */
3134 curproxy->options |= PR_O_DISABLE404;
3135 }
Willy Tarreauef781042010-01-27 11:53:01 +01003136 else if (strcmp(args[1], "send-state") == 0) {
3137 /* enable emission of the apparent state of a server in HTTP checks */
3138 curproxy->options2 |= PR_O2_CHK_SNDST;
3139 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003140 else if (strcmp(args[1], "expect") == 0) {
3141 const char *ptr_arg;
3142 int cur_arg;
3143
3144 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3145 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149
3150 cur_arg = 2;
3151 /* consider exclamation marks, sole or at the beginning of a word */
3152 while (*(ptr_arg = args[cur_arg])) {
3153 while (*ptr_arg == '!') {
3154 curproxy->options2 ^= PR_O2_EXP_INV;
3155 ptr_arg++;
3156 }
3157 if (*ptr_arg)
3158 break;
3159 cur_arg++;
3160 }
3161 /* now ptr_arg points to the beginning of a word past any possible
3162 * exclamation mark, and cur_arg is the argument which holds this word.
3163 */
3164 if (strcmp(ptr_arg, "status") == 0) {
3165 if (!*(args[cur_arg + 1])) {
3166 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3167 file, linenum, args[0], args[1], ptr_arg);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171 curproxy->options2 |= PR_O2_EXP_STS;
3172 curproxy->expect_str = strdup(args[cur_arg + 1]);
3173 }
3174 else if (strcmp(ptr_arg, "string") == 0) {
3175 if (!*(args[cur_arg + 1])) {
3176 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3177 file, linenum, args[0], args[1], ptr_arg);
3178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
3180 }
3181 curproxy->options2 |= PR_O2_EXP_STR;
3182 curproxy->expect_str = strdup(args[cur_arg + 1]);
3183 }
3184 else if (strcmp(ptr_arg, "rstatus") == 0) {
3185 if (!*(args[cur_arg + 1])) {
3186 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3187 file, linenum, args[0], args[1], ptr_arg);
3188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
3190 }
3191 curproxy->options2 |= PR_O2_EXP_RSTS;
3192 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3193 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3194 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3195 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198 }
3199 }
3200 else if (strcmp(ptr_arg, "rstring") == 0) {
3201 if (!*(args[cur_arg + 1])) {
3202 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3203 file, linenum, args[0], args[1], ptr_arg);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
3207 curproxy->options2 |= PR_O2_EXP_RSTR;
3208 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3209 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3210 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3211 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
3214 }
3215 }
3216 else {
3217 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3218 file, linenum, args[0], args[1], ptr_arg);
3219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
3221 }
3222 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003223 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003224 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003227 }
3228 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003229 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003230 if (curproxy == &defproxy) {
3231 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003234 }
3235
Willy Tarreaub80c2302007-11-30 20:51:32 +01003236 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003238
3239 if (strcmp(args[1], "fail") == 0) {
3240 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003241 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003242 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3243 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003246 }
3247
Willy Tarreauef6494c2010-01-28 17:12:36 +01003248 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003249 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3250 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003253 }
3254 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3255 }
3256 else {
3257 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003260 }
3261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262#ifdef TPROXY
3263 else if (!strcmp(args[0], "transparent")) {
3264 /* enable transparent proxy connections */
3265 curproxy->options |= PR_O_TRANSP;
3266 }
3267#endif
3268 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003269 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003271
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 if (*(args[1]) == 0) {
3273 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 curproxy->maxconn = atol(args[1]);
3278 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003279 else if (!strcmp(args[0], "backlog")) { /* backlog */
3280 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003282
3283 if (*(args[1]) == 0) {
3284 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003287 }
3288 curproxy->backlog = atol(args[1]);
3289 }
Willy Tarreau86034312006-12-29 00:10:33 +01003290 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003291 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003292 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003293
Willy Tarreau86034312006-12-29 00:10:33 +01003294 if (*(args[1]) == 0) {
3295 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003298 }
3299 curproxy->fullconn = atol(args[1]);
3300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3302 if (*(args[1]) == 0) {
3303 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003307 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3308 if (err) {
3309 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3310 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003313 }
3314 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }
3316 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003317 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 if (curproxy == &defproxy) {
3319 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003323 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003325
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 if (strchr(args[1], ':') == NULL) {
3327 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003331 sk = str2sa(args[1]);
3332 if (!sk) {
3333 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
3336 }
3337 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
3339 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003340 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003342
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003343 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003344 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3345 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003350 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3351 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3352 err_code |= ERR_WARN;
3353
3354 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3355 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3356 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3357 }
3358 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3359 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3360 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3361 }
3362 else {
3363 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
3367 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003368 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003370 char *rport, *raddr;
3371 short realport = 0;
3372 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003374 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003379 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381
3382 if (!*args[2]) {
3383 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3384 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003388
3389 err = invalid_char(args[1]);
3390 if (err) {
3391 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3392 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003395 }
3396
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003397 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003398 struct sockaddr_in *sk;
3399
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003400 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3401 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3402 err_code |= ERR_ALERT | ERR_ABORT;
3403 goto out;
3404 }
3405
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003406 /* the servers are linked backwards first */
3407 newsrv->next = curproxy->srv;
3408 curproxy->srv = newsrv;
3409 newsrv->proxy = curproxy;
3410 newsrv->conf.file = file;
3411 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003413 LIST_INIT(&newsrv->pendconns);
3414 do_check = 0;
3415 newsrv->state = SRV_RUNNING; /* early server setup */
3416 newsrv->last_change = now.tv_sec;
3417 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003419 /* several ways to check the port component :
3420 * - IP => port=+0, relative
3421 * - IP: => port=+0, relative
3422 * - IP:N => port=N, absolute
3423 * - IP:+N => port=+N, relative
3424 * - IP:-N => port=-N, relative
3425 */
3426 raddr = strdup(args[2]);
3427 rport = strchr(raddr, ':');
3428 if (rport) {
3429 *rport++ = 0;
3430 realport = atol(rport);
3431 if (!isdigit((unsigned char)*rport))
3432 newsrv->state |= SRV_MAPPORTS;
3433 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003435
Willy Tarreaud5191e72010-02-09 20:50:45 +01003436 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003437 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003438 if (!sk) {
3439 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
3443 newsrv->addr = *sk;
3444 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003445
3446 newsrv->check_port = curproxy->defsrv.check_port;
3447 newsrv->inter = curproxy->defsrv.inter;
3448 newsrv->fastinter = curproxy->defsrv.fastinter;
3449 newsrv->downinter = curproxy->defsrv.downinter;
3450 newsrv->rise = curproxy->defsrv.rise;
3451 newsrv->fall = curproxy->defsrv.fall;
3452 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3453 newsrv->minconn = curproxy->defsrv.minconn;
3454 newsrv->maxconn = curproxy->defsrv.maxconn;
3455 newsrv->slowstart = curproxy->defsrv.slowstart;
3456 newsrv->onerror = curproxy->defsrv.onerror;
3457 newsrv->consecutive_errors_limit
3458 = curproxy->defsrv.consecutive_errors_limit;
3459 newsrv->uweight = newsrv->iweight
3460 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003462 newsrv->curfd = -1; /* no health-check in progress */
3463 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003464
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003465 cur_arg = 3;
3466 } else {
3467 newsrv = &curproxy->defsrv;
3468 cur_arg = 1;
3469 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003470
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003472 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003473 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003474
3475 if (!*args[cur_arg + 1]) {
3476 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3477 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003480 }
3481
3482 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003483 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003484
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003485 if (newsrv->puid <= 0) {
3486 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003487 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003490 }
3491
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003492 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3493 if (node) {
3494 struct server *target = container_of(node, struct server, conf.id);
3495 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3496 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003501 cur_arg += 2;
3502 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003503 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 newsrv->cookie = strdup(args[cur_arg + 1]);
3505 newsrv->cklen = strlen(args[cur_arg + 1]);
3506 cur_arg += 2;
3507 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003508 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003509 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3510 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3511 cur_arg += 2;
3512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003514 if (!*args[cur_arg + 1]) {
3515 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3516 file, linenum, args[cur_arg]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003522 if (newsrv->rise <= 0) {
3523 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3524 file, linenum, args[cur_arg]);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
3527 }
3528
Willy Tarreau96839092010-03-29 10:02:24 +02003529 if (newsrv->health)
3530 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 cur_arg += 2;
3532 }
3533 else if (!strcmp(args[cur_arg], "fall")) {
3534 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003535
3536 if (!*args[cur_arg + 1]) {
3537 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3538 file, linenum, args[cur_arg]);
3539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
3541 }
3542
3543 if (newsrv->fall <= 0) {
3544 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3545 file, linenum, args[cur_arg]);
3546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
3548 }
3549
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 cur_arg += 2;
3551 }
3552 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003553 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3554 if (err) {
3555 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3556 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003559 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003560 if (val <= 0) {
3561 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3562 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003565 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003566 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 cur_arg += 2;
3568 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003569 else if (!strcmp(args[cur_arg], "fastinter")) {
3570 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3571 if (err) {
3572 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3573 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003576 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003577 if (val <= 0) {
3578 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3579 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003582 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003583 newsrv->fastinter = val;
3584 cur_arg += 2;
3585 }
3586 else if (!strcmp(args[cur_arg], "downinter")) {
3587 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3588 if (err) {
3589 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3590 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003593 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003594 if (val <= 0) {
3595 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3596 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003599 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003600 newsrv->downinter = val;
3601 cur_arg += 2;
3602 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003603 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003604 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3605 if (!sk) {
3606 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
3609 }
3610 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003611 cur_arg += 2;
3612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 else if (!strcmp(args[cur_arg], "port")) {
3614 newsrv->check_port = atol(args[cur_arg + 1]);
3615 cur_arg += 2;
3616 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003617 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 newsrv->state |= SRV_BACKUP;
3619 cur_arg ++;
3620 }
3621 else if (!strcmp(args[cur_arg], "weight")) {
3622 int w;
3623 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003624 if (w < 0 || w > 256) {
3625 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003630 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 cur_arg += 2;
3632 }
3633 else if (!strcmp(args[cur_arg], "minconn")) {
3634 newsrv->minconn = atol(args[cur_arg + 1]);
3635 cur_arg += 2;
3636 }
3637 else if (!strcmp(args[cur_arg], "maxconn")) {
3638 newsrv->maxconn = atol(args[cur_arg + 1]);
3639 cur_arg += 2;
3640 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003641 else if (!strcmp(args[cur_arg], "maxqueue")) {
3642 newsrv->maxqueue = atol(args[cur_arg + 1]);
3643 cur_arg += 2;
3644 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003645 else if (!strcmp(args[cur_arg], "slowstart")) {
3646 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003647 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003648 if (err) {
3649 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3650 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003653 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003654 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003655 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3656 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003659 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003660 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003661 cur_arg += 2;
3662 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003663 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003664
3665 if (!*args[cur_arg + 1]) {
3666 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3667 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003670 }
3671
3672 newsrv->trackit = strdup(args[cur_arg + 1]);
3673
3674 cur_arg += 2;
3675 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003676 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 global.maxsock++;
3678 do_check = 1;
3679 cur_arg += 1;
3680 }
Willy Tarreau96839092010-03-29 10:02:24 +02003681 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3682 newsrv->state |= SRV_MAINTAIN;
3683 newsrv->state &= ~SRV_RUNNING;
3684 newsrv->health = 0;
3685 cur_arg += 1;
3686 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003687 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003688 if (!strcmp(args[cur_arg + 1], "none"))
3689 newsrv->observe = HANA_OBS_NONE;
3690 else if (!strcmp(args[cur_arg + 1], "layer4"))
3691 newsrv->observe = HANA_OBS_LAYER4;
3692 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3693 if (curproxy->mode != PR_MODE_HTTP) {
3694 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3695 file, linenum, args[cur_arg + 1]);
3696 err_code |= ERR_ALERT;
3697 }
3698 newsrv->observe = HANA_OBS_LAYER7;
3699 }
3700 else {
3701 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003702 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003703 file, linenum, args[cur_arg], args[cur_arg + 1]);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707
3708 cur_arg += 2;
3709 }
3710 else if (!strcmp(args[cur_arg], "on-error")) {
3711 if (!strcmp(args[cur_arg + 1], "fastinter"))
3712 newsrv->onerror = HANA_ONERR_FASTINTER;
3713 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3714 newsrv->onerror = HANA_ONERR_FAILCHK;
3715 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3716 newsrv->onerror = HANA_ONERR_SUDDTH;
3717 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3718 newsrv->onerror = HANA_ONERR_MARKDWN;
3719 else {
3720 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003721 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003722 file, linenum, args[cur_arg], args[cur_arg + 1]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726
3727 cur_arg += 2;
3728 }
3729 else if (!strcmp(args[cur_arg], "error-limit")) {
3730 if (!*args[cur_arg + 1]) {
3731 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3732 file, linenum, args[cur_arg]);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736
3737 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3738
3739 if (newsrv->consecutive_errors_limit <= 0) {
3740 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3741 file, linenum, args[cur_arg]);
3742 err_code |= ERR_ALERT | ERR_FATAL;
3743 goto out;
3744 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003745 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003746 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003747 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003748 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003749 struct sockaddr_in *sk;
3750
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003752#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003753 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003754 file, linenum, "source", "usesrc");
3755#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003756 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003758#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 }
3762 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003763 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3764 if (!sk) {
3765 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
3768 }
3769 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003770
3771 if (port_low != port_high) {
3772 int i;
3773 if (port_low <= 0 || port_low > 65535 ||
3774 port_high <= 0 || port_high > 65535 ||
3775 port_low > port_high) {
3776 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3777 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003780 }
3781 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3782 for (i = 0; i < newsrv->sport_range->size; i++)
3783 newsrv->sport_range->ports[i] = port_low + i;
3784 }
3785
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003787 while (*(args[cur_arg])) {
3788 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003789#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3790#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003791 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3792 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3793 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003796 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003797#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003798 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003799 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01003800 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003803 }
3804 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003805 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003806 newsrv->state |= SRV_TPROXY_CLI;
3807 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003808 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003809 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003810 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3811 char *name, *end;
3812
3813 name = args[cur_arg+1] + 7;
3814 while (isspace(*name))
3815 name++;
3816
3817 end = name;
3818 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3819 end++;
3820
3821 newsrv->state &= ~SRV_TPROXY_MASK;
3822 newsrv->state |= SRV_TPROXY_DYN;
3823 newsrv->bind_hdr_name = calloc(1, end - name + 1);
3824 newsrv->bind_hdr_len = end - name;
3825 memcpy(newsrv->bind_hdr_name, name, end - name);
3826 newsrv->bind_hdr_name[end-name] = '\0';
3827 newsrv->bind_hdr_occ = -1;
3828
3829 /* now look for an occurrence number */
3830 while (isspace(*end))
3831 end++;
3832 if (*end == ',') {
3833 end++;
3834 name = end;
3835 if (*end == '-')
3836 end++;
3837 while (isdigit(*end))
3838 end++;
3839 newsrv->bind_hdr_occ = strl2ic(name, end-name);
3840 }
3841
3842 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
3843 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3844 " occurrences values smaller than %d.\n",
3845 file, linenum, MAX_HDR_HISTORY);
3846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01003849 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003850 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3851 if (!sk) {
3852 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
3855 }
3856 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003857 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003858 }
3859 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003860#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003861 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003862#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003863 cur_arg += 2;
3864 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003865#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003866 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003867 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003870#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3871 } /* "usesrc" */
3872
3873 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3874#ifdef SO_BINDTODEVICE
3875 if (!*args[cur_arg + 1]) {
3876 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3877 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003880 }
3881 if (newsrv->iface_name)
3882 free(newsrv->iface_name);
3883
3884 newsrv->iface_name = strdup(args[cur_arg + 1]);
3885 newsrv->iface_len = strlen(newsrv->iface_name);
3886 global.last_checks |= LSTCHK_NETADM;
3887#else
3888 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3889 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003892#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003893 cur_arg += 2;
3894 continue;
3895 }
3896 /* this keyword in not an option of "source" */
3897 break;
3898 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003900 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003901 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3902 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003907 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003908 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 +01003909 file, linenum, newsrv->id);
3910 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003911 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 +01003912 file, linenum);
3913
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916 }
3917 }
3918
3919 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003920 if (newsrv->trackit) {
3921 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3922 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003925 }
3926
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003927 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3928 newsrv->check_port = newsrv->check_addr.sin_port;
3929
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3931 newsrv->check_port = realport; /* by default */
3932 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003933 /* not yet valid, because no port was set on
3934 * the server either. We'll check if we have
3935 * a known port on the first listener.
3936 */
3937 struct listener *l;
3938 l = curproxy->listen;
3939 if (l) {
3940 int port;
3941 port = (l->addr.ss_family == AF_INET6)
3942 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3943 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3944 newsrv->check_port = port;
3945 }
3946 }
3947 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3949 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003953
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003954 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02003955 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003956 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3957 err_code |= ERR_ALERT | ERR_ABORT;
3958 goto out;
3959 }
3960
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003961 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 newsrv->state |= SRV_CHECKED;
3963 }
3964
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003965 if (!defsrv) {
3966 if (newsrv->state & SRV_BACKUP)
3967 curproxy->srv_bck++;
3968 else
3969 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003970
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003971 newsrv->prev_state = newsrv->state;
3972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 }
3974 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003975 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 int facility;
3977
3978 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3979 curproxy->logfac1 = global.logfac1;
3980 curproxy->logsrv1 = global.logsrv1;
3981 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003982 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 curproxy->logfac2 = global.logfac2;
3984 curproxy->logsrv2 = global.logsrv2;
3985 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003986 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987 }
3988 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003989 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990
3991 facility = get_log_facility(args[2]);
3992 if (facility < 0) {
3993 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3994 exit(1);
3995 }
3996
3997 level = 7; /* max syslog level = debug */
3998 if (*(args[3])) {
3999 level = get_log_level(args[3]);
4000 if (level < 0) {
4001 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4002 exit(1);
4003 }
4004 }
4005
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004006 minlvl = 0; /* limit syslog level to this level (emerg) */
4007 if (*(args[4])) {
4008 minlvl = get_log_level(args[4]);
4009 if (level < 0) {
4010 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4011 exit(1);
4012 }
4013 }
4014
Robert Tsai81ae1952007-12-05 10:47:29 +01004015 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004016 struct sockaddr_un *sk = str2sun(args[1]);
4017 if (!sk) {
4018 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4019 args[1], (int)sizeof(sk->sun_path) - 1);
4020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
4022 }
4023 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004024 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004025 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004026 struct sockaddr_in *sk = str2sa(args[1]);
4027 if (!sk) {
4028 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
4031 }
4032 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004033 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004034 if (!logsrv.u.in.sin_port) {
4035 logsrv.u.in.sin_port =
4036 htons(SYSLOG_PORT);
4037 }
4038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039
4040 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004041 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 curproxy->logfac1 = facility;
4043 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004044 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 }
4046 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004047 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 curproxy->logfac2 = facility;
4049 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004050 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 }
4052 else {
4053 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 }
4057 }
4058 else {
4059 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4060 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 }
4064 }
4065 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004066 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004067 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004068
Willy Tarreau977b8e42006-12-29 14:19:17 +01004069 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004070 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004071
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004073 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4074 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004078
4079 /* we must first clear any optional default setting */
4080 curproxy->options &= ~PR_O_TPXY_MASK;
4081 free(curproxy->iface_name);
4082 curproxy->iface_name = NULL;
4083 curproxy->iface_len = 0;
4084
Willy Tarreaud5191e72010-02-09 20:50:45 +01004085 sk = str2sa(args[1]);
4086 if (!sk) {
4087 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
4091 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004093
4094 cur_arg = 2;
4095 while (*(args[cur_arg])) {
4096 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004097#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4098#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004099 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4100 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4101 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004104 }
4105#endif
4106 if (!*args[cur_arg + 1]) {
4107 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4108 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004111 }
4112
4113 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004114 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004115 curproxy->options |= PR_O_TPXY_CLI;
4116 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004117 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004118 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004119 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4120 char *name, *end;
4121
4122 name = args[cur_arg+1] + 7;
4123 while (isspace(*name))
4124 name++;
4125
4126 end = name;
4127 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4128 end++;
4129
4130 curproxy->options &= ~PR_O_TPXY_MASK;
4131 curproxy->options |= PR_O_TPXY_DYN;
4132 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4133 curproxy->bind_hdr_len = end - name;
4134 memcpy(curproxy->bind_hdr_name, name, end - name);
4135 curproxy->bind_hdr_name[end-name] = '\0';
4136 curproxy->bind_hdr_occ = -1;
4137
4138 /* now look for an occurrence number */
4139 while (isspace(*end))
4140 end++;
4141 if (*end == ',') {
4142 end++;
4143 name = end;
4144 if (*end == '-')
4145 end++;
4146 while (isdigit(*end))
4147 end++;
4148 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4149 }
4150
4151 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4152 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4153 " occurrences values smaller than %d.\n",
4154 file, linenum, MAX_HDR_HISTORY);
4155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
4157 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004158 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004159 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4160 if (!sk) {
4161 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004166 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004167 }
4168 global.last_checks |= LSTCHK_NETADM;
4169#if !defined(CONFIG_HAP_LINUX_TPROXY)
4170 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004171#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004172#else /* no TPROXY support */
4173 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004174 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004177#endif
4178 cur_arg += 2;
4179 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004180 }
4181
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004182 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4183#ifdef SO_BINDTODEVICE
4184 if (!*args[cur_arg + 1]) {
4185 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004189 }
4190 if (curproxy->iface_name)
4191 free(curproxy->iface_name);
4192
4193 curproxy->iface_name = strdup(args[cur_arg + 1]);
4194 curproxy->iface_len = strlen(curproxy->iface_name);
4195 global.last_checks |= LSTCHK_NETADM;
4196#else
4197 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4198 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004201#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004202 cur_arg += 2;
4203 continue;
4204 }
4205 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4206 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004211 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4212 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4213 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004217 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004218 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004224
4225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4226 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004227 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 }
4231 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4233 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004237 }
4238 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4240 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 }
4245 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4247 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 }
4252 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4254 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004259 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4261 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004262 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004264 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004265 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004266 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4268 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004269 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004271 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004272 }
4273 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4275 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004276 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004278 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004281 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4283 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004287
4288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4289 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004290 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 }
4294 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4296 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 }
4301 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004302 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4303 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004304 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004305 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 }
4308 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004309 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4310 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004311 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004312 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 }
4315 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004316 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4317 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004318 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004319 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004321 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004322 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004323 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4324 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004325 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004326 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004327 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004330 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004331
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 if (curproxy == &defproxy) {
4333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004337 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004338 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 if (*(args[1]) == 0) {
4341 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004345
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004346 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4347 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4348 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4349 file, linenum, args[0]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4354 }
4355 else if (*args[2]) {
4356 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4357 file, linenum, args[0], args[2]);
4358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
4360 }
4361
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004362 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004363 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004364 wl->s = strdup(args[1]);
4365 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004366 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 }
4368 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004369 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4371 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004375
Willy Tarreauade5ec42010-01-28 19:33:49 +01004376 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4377 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004378 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004379 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 }
4382 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004383 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4384 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004385 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004386 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 }
4389 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004390 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4391 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004392 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004393 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 }
4396 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004397 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 }
4403
Willy Tarreauade5ec42010-01-28 19:33:49 +01004404 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4405 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004406 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004407 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004409 }
4410 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004411 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4412 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004413 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004414 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 }
4417 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004418 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4419 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004420 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004421 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 }
4424 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004425 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004426
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 if (curproxy == &defproxy) {
4428 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004432 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004434
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435 if (*(args[1]) == 0) {
4436 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 }
4440
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004441 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4442 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4443 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4444 file, linenum, args[0]);
4445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
4447 }
4448 err_code |= warnif_cond_requires_req(cond, file, linenum);
4449 }
4450 else if (*args[2]) {
4451 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4452 file, linenum, args[0], args[2]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004457 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004458 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004459 wl->s = strdup(args[1]);
4460 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 }
4462 else if (!strcmp(args[0], "errorloc") ||
4463 !strcmp(args[0], "errorloc302") ||
4464 !strcmp(args[0], "errorloc303")) { /* error location */
4465 int errnum, errlen;
4466 char *err;
4467
Willy Tarreau977b8e42006-12-29 14:19:17 +01004468 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004470
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004472 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
4476
4477 errnum = atol(args[1]);
4478 if (!strcmp(args[0], "errorloc303")) {
4479 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4480 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4481 } else {
4482 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4483 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4484 }
4485
Willy Tarreau0f772532006-12-23 20:51:41 +01004486 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4487 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004488 chunk_destroy(&curproxy->errmsg[rc]);
4489 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004490 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004493
4494 if (rc >= HTTP_ERR_SIZE) {
4495 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4496 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 free(err);
4498 }
4499 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004500 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4501 int errnum, errlen, fd;
4502 char *err;
4503 struct stat stat;
4504
4505 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004507
4508 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004509 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004512 }
4513
4514 fd = open(args[2], O_RDONLY);
4515 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4516 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4517 file, linenum, args[2], args[1]);
4518 if (fd >= 0)
4519 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004522 }
4523
Willy Tarreau27a674e2009-08-17 07:23:33 +02004524 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004525 errlen = stat.st_size;
4526 } else {
4527 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004528 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004529 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004530 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004531 }
4532
4533 err = malloc(errlen); /* malloc() must succeed during parsing */
4534 errnum = read(fd, err, errlen);
4535 if (errnum != errlen) {
4536 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4537 file, linenum, args[2], args[1]);
4538 close(fd);
4539 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004542 }
4543 close(fd);
4544
4545 errnum = atol(args[1]);
4546 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4547 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004548 chunk_destroy(&curproxy->errmsg[rc]);
4549 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004550 break;
4551 }
4552 }
4553
4554 if (rc >= HTTP_ERR_SIZE) {
4555 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4556 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004557 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004558 free(err);
4559 }
4560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004562 struct cfg_kw_list *kwl;
4563 int index;
4564
4565 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4566 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4567 if (kwl->kw[index].section != CFG_LISTEN)
4568 continue;
4569 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4570 /* prepare error message just in case */
4571 snprintf(trash, sizeof(trash),
4572 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004573 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4574 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004575 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004578 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004579 else if (rc > 0) {
4580 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_WARN;
4582 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004583 }
Willy Tarreau93893792009-07-23 13:19:11 +02004584 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004585 }
4586 }
4587 }
4588
Willy Tarreau6daf3432008-01-22 16:44:08 +01004589 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
Willy Tarreau93893792009-07-23 13:19:11 +02004593 out:
4594 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595}
4596
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004597int
4598cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4599{
4600
4601 int err_code = 0;
4602 const char *err;
4603
4604 if (!strcmp(args[0], "userlist")) { /* new userlist */
4605 struct userlist *newul;
4606
4607 if (!*args[1]) {
4608 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4609 file, linenum, args[0]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
4613
4614 err = invalid_char(args[1]);
4615 if (err) {
4616 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4617 file, linenum, *err, args[0], args[1]);
4618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
4621
4622 for (newul = userlist; newul; newul = newul->next)
4623 if (!strcmp(newul->name, args[1])) {
4624 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4625 file, linenum, args[1]);
4626 err_code |= ERR_WARN;
4627 goto out;
4628 }
4629
4630 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4631 if (!newul) {
4632 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4633 err_code |= ERR_ALERT | ERR_ABORT;
4634 goto out;
4635 }
4636
4637 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4638 newul->name = strdup(args[1]);
4639
4640 if (!newul->groupusers | !newul->name) {
4641 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4642 err_code |= ERR_ALERT | ERR_ABORT;
4643 goto out;
4644 }
4645
4646 newul->next = userlist;
4647 userlist = newul;
4648
4649 } else if (!strcmp(args[0], "group")) { /* new group */
4650 int cur_arg, i;
4651 const char *err;
4652
4653 if (!*args[1]) {
4654 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4655 file, linenum, args[0]);
4656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
4658 }
4659
4660 err = invalid_char(args[1]);
4661 if (err) {
4662 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4663 file, linenum, *err, args[0], args[1]);
4664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
4667
4668 for(i = 0; i < userlist->grpcnt; i++)
4669 if (!strcmp(userlist->groups[i], args[1])) {
4670 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4671 file, linenum, args[1], userlist->name);
4672 err_code |= ERR_ALERT;
4673 goto out;
4674 }
4675
4676 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4677 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4678 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
4681 }
4682
4683 cur_arg = 2;
4684
4685 while (*args[cur_arg]) {
4686 if (!strcmp(args[cur_arg], "users")) {
4687 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4688 cur_arg += 2;
4689 continue;
4690 } else {
4691 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4692 file, linenum, args[0]);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
4696 }
4697
4698 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4699 } else if (!strcmp(args[0], "user")) { /* new user */
4700 struct auth_users *newuser;
4701 int cur_arg;
4702
4703 if (!*args[1]) {
4704 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4705 file, linenum, args[0]);
4706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708 }
4709
4710 for (newuser = userlist->users; newuser; newuser = newuser->next)
4711 if (!strcmp(newuser->user, args[1])) {
4712 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4713 file, linenum, args[1], userlist->name);
4714 err_code |= ERR_ALERT;
4715 goto out;
4716 }
4717
4718 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4719 if (!newuser) {
4720 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4721 err_code |= ERR_ALERT | ERR_ABORT;
4722 goto out;
4723 }
4724
4725 newuser->user = strdup(args[1]);
4726
4727 newuser->next = userlist->users;
4728 userlist->users = newuser;
4729
4730 cur_arg = 2;
4731
4732 while (*args[cur_arg]) {
4733 if (!strcmp(args[cur_arg], "password")) {
4734#ifndef CONFIG_HAP_CRYPT
4735 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4736 file, linenum);
4737 err_code |= ERR_ALERT;
4738#endif
4739 newuser->pass = strdup(args[cur_arg + 1]);
4740 cur_arg += 2;
4741 continue;
4742 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4743 newuser->pass = strdup(args[cur_arg + 1]);
4744 newuser->flags |= AU_O_INSECURE;
4745 cur_arg += 2;
4746 continue;
4747 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004748 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004749 cur_arg += 2;
4750 continue;
4751 } else {
4752 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4753 file, linenum, args[0]);
4754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
4756 }
4757 }
4758 } else {
4759 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4760 err_code |= ERR_ALERT | ERR_FATAL;
4761 }
4762
4763out:
4764 return err_code;
4765}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766
4767/*
4768 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004769 * Returns the error code, 0 if OK, or any combination of :
4770 * - ERR_ABORT: must abort ASAP
4771 * - ERR_FATAL: we can continue parsing but not start the service
4772 * - ERR_WARN: a warning has been emitted
4773 * - ERR_ALERT: an alert has been emitted
4774 * Only the two first ones can stop processing, the two others are just
4775 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004777int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004779 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 FILE *f;
4781 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004783 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784
Willy Tarreaubaaee002006-06-26 02:48:02 +02004785 if ((f=fopen(file,"r")) == NULL)
4786 return -1;
4787
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004788 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004789 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004790 char *end;
4791 char *args[MAX_LINE_ARGS + 1];
4792 char *line = thisline;
4793
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 linenum++;
4795
4796 end = line + strlen(line);
4797
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004798 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4799 /* Check if we reached the limit and the last char is not \n.
4800 * Watch out for the last line without the terminating '\n'!
4801 */
4802 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004803 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004804 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004805 }
4806
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004808 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 line++;
4810
4811 arg = 0;
4812 args[arg] = line;
4813
4814 while (*line && arg < MAX_LINE_ARGS) {
4815 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4816 * C equivalent value. Other combinations left unchanged (eg: \1).
4817 */
4818 if (*line == '\\') {
4819 int skip = 0;
4820 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4821 *line = line[1];
4822 skip = 1;
4823 }
4824 else if (line[1] == 'r') {
4825 *line = '\r';
4826 skip = 1;
4827 }
4828 else if (line[1] == 'n') {
4829 *line = '\n';
4830 skip = 1;
4831 }
4832 else if (line[1] == 't') {
4833 *line = '\t';
4834 skip = 1;
4835 }
4836 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004837 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 unsigned char hex1, hex2;
4839 hex1 = toupper(line[2]) - '0';
4840 hex2 = toupper(line[3]) - '0';
4841 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4842 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4843 *line = (hex1<<4) + hex2;
4844 skip = 3;
4845 }
4846 else {
4847 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004848 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
4850 }
4851 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004852 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 end -= skip;
4854 }
4855 line++;
4856 }
4857 else if (*line == '#' || *line == '\n' || *line == '\r') {
4858 /* end of string, end of loop */
4859 *line = 0;
4860 break;
4861 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004862 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004864 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004865 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 line++;
4867 args[++arg] = line;
4868 }
4869 else {
4870 line++;
4871 }
4872 }
4873
4874 /* empty line */
4875 if (!**args)
4876 continue;
4877
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004878 if (*line) {
4879 /* we had to stop due to too many args.
4880 * Let's terminate the string, print the offending part then cut the
4881 * last arg.
4882 */
4883 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4884 line++;
4885 *line = '\0';
4886
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004887 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004888 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004889 err_code |= ERR_ALERT | ERR_FATAL;
4890 args[arg] = line;
4891 }
4892
Willy Tarreau540abe42007-05-02 20:50:16 +02004893 /* zero out remaining args and ensure that at least one entry
4894 * is zeroed out.
4895 */
4896 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 args[arg] = line;
4898 }
4899
Willy Tarreau3842f002009-06-14 11:39:52 +02004900 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004901 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004902 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004903 for (arg=0; *args[arg+1]; arg++)
4904 args[arg] = args[arg+1]; // shift args after inversion
4905 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004906 else if (!strcmp(args[0], "default")) {
4907 kwm = KWM_DEF;
4908 for (arg=0; *args[arg+1]; arg++)
4909 args[arg] = args[arg+1]; // shift args after inversion
4910 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004911
Willy Tarreau3842f002009-06-14 11:39:52 +02004912 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4913 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004914 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004915 }
4916
Willy Tarreau977b8e42006-12-29 14:19:17 +01004917 if (!strcmp(args[0], "listen") ||
4918 !strcmp(args[0], "frontend") ||
4919 !strcmp(args[0], "backend") ||
4920 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004921 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004923 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004924 cursection = strdup(args[0]);
4925 }
4926 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004928 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004929 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004930 } else if (!strcmp(args[0], "userlist")) {
4931 confsect = CFG_USERLIST;
4932 free(cursection);
4933 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004934 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 /* else it's a section keyword */
4936
4937 switch (confsect) {
4938 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 break;
4941 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004942 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004944 case CFG_USERLIST:
4945 err_code |= cfg_parse_users(file, linenum, args, kwm);
4946 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004948 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004951
4952 if (err_code & ERR_ABORT)
4953 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004955 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004956 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004958 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004959}
4960
Willy Tarreaubb925012009-07-23 13:36:36 +02004961/*
4962 * Returns the error code, 0 if OK, or any combination of :
4963 * - ERR_ABORT: must abort ASAP
4964 * - ERR_FATAL: we can continue parsing but not start the service
4965 * - ERR_WARN: a warning has been emitted
4966 * - ERR_ALERT: an alert has been emitted
4967 * Only the two first ones can stop processing, the two others are just
4968 * indicators.
4969 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004970int check_config_validity()
4971{
4972 int cfgerr = 0;
4973 struct proxy *curproxy = NULL;
4974 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004975 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004976 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004977 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978
4979 /*
4980 * Now, check for the integrity of all that we have collected.
4981 */
4982
4983 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004984 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004986 /* first, we will invert the proxy list order */
4987 curproxy = NULL;
4988 while (proxy) {
4989 struct proxy *next;
4990
4991 next = proxy->next;
4992 proxy->next = curproxy;
4993 curproxy = proxy;
4994 if (!next)
4995 break;
4996 proxy = next;
4997 }
4998
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005000 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004
5005 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005006 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005007 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005008 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005009 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005010 unsigned int next_id;
5011
5012 if (!curproxy->uuid) {
5013 /* proxy ID not set, use automatic numbering with first
5014 * spare entry starting with next_pxid.
5015 */
5016 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5017 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5018 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005019 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005020 next_pxid++;
5021
Willy Tarreau55ea7572007-06-17 19:56:27 +02005022
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005024 /* ensure we don't keep listeners uselessly bound */
5025 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 curproxy = curproxy->next;
5027 continue;
5028 }
5029
Willy Tarreauff01a212009-03-15 13:46:16 +01005030 switch (curproxy->mode) {
5031 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005032 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005033 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005034 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5035 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005036 cfgerr++;
5037 }
5038
5039 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005040 Warning("config : servers will be ignored for %s '%s'.\n",
5041 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005042 break;
5043
5044 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005045 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005046 break;
5047
5048 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005049 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005050 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005051 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5052 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005053 cfgerr++;
5054 }
5055 break;
5056 }
5057
5058 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005059 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5060 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 cfgerr++;
5062 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005063
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005064 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005065 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005066 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005067 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5068 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005069 cfgerr++;
5070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005072 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005073 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5074 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005075 cfgerr++;
5076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005078 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005079 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5080 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005081 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005082 }
5083 }
5084 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5085 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5086 /* If no LB algo is set in a backend, and we're not in
5087 * transparent mode, dispatch mode nor proxy mode, we
5088 * want to use balance roundrobin by default.
5089 */
5090 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5091 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 }
5093 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005094
Willy Tarreau82936582007-11-30 15:20:09 +01005095 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5096 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005097 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5098 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005099 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005100 }
5101
Willy Tarreauef781042010-01-27 11:53:01 +01005102 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5103 curproxy->options &= ~PR_O2_CHK_SNDST;
5104 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5105 "send-state", proxy_type_str(curproxy), curproxy->id);
5106 err_code |= ERR_WARN;
5107 }
5108
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005109 /* if a default backend was specified, let's find it */
5110 if (curproxy->defbe.name) {
5111 struct proxy *target;
5112
Alex Williams96532db2009-11-01 21:27:13 -05005113 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005114 if (!target) {
5115 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5116 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005117 cfgerr++;
5118 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005119 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5120 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005121 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005122 } else {
5123 free(curproxy->defbe.name);
5124 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005125 /* we force the backend to be present on at least all of
5126 * the frontend's processes.
5127 */
5128 target->bind_proc = curproxy->bind_proc ?
5129 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 }
5131 }
5132
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005133 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005134 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5135 /* map jump target for ACT_SETBE in req_rep chain */
5136 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005137 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005138 struct proxy *target;
5139
Willy Tarreaua496b602006-12-17 23:15:24 +01005140 if (exp->action != ACT_SETBE)
5141 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005142
Alex Williams96532db2009-11-01 21:27:13 -05005143 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005144 if (!target) {
5145 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5146 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005147 cfgerr++;
5148 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005149 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5150 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005151 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005152 } else {
5153 free((void *)exp->replace);
5154 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005155 /* we force the backend to be present on at least all of
5156 * the frontend's processes.
5157 */
5158 target->bind_proc = curproxy->bind_proc ?
5159 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005160 }
5161 }
5162 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005163
5164 /* find the target proxy for 'use_backend' rules */
5165 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005166 struct proxy *target;
5167
Alex Williams96532db2009-11-01 21:27:13 -05005168 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005169
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005170 if (!target) {
5171 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5172 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005173 cfgerr++;
5174 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005175 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5176 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005177 cfgerr++;
5178 } else {
5179 free((void *)rule->be.name);
5180 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005181 /* we force the backend to be present on at least all of
5182 * the frontend's processes.
5183 */
5184 target->bind_proc = curproxy->bind_proc ?
5185 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005186 }
5187 }
5188
Emeric Brunb982a3d2010-01-04 15:45:53 +01005189 /* find the target table for 'stick' rules */
5190 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5191 struct proxy *target;
5192
Emeric Brun1d33b292010-01-04 15:47:17 +01005193 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5194 if (mrule->flags & STK_IS_STORE)
5195 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5196
Emeric Brunb982a3d2010-01-04 15:45:53 +01005197 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005198 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005199 else
5200 target = curproxy;
5201
5202 if (!target) {
5203 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5204 curproxy->id, mrule->table.name);
5205 cfgerr++;
5206 }
5207 else if (target->table.size == 0) {
5208 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5209 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5210 cfgerr++;
5211 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005212 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005213 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5214 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5215 cfgerr++;
5216 }
5217 else {
5218 free((void *)mrule->table.name);
5219 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005220 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005221 }
5222 }
5223
5224 /* find the target table for 'store response' rules */
5225 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5226 struct proxy *target;
5227
Emeric Brun1d33b292010-01-04 15:47:17 +01005228 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5229
Emeric Brunb982a3d2010-01-04 15:45:53 +01005230 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005231 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005232 else
5233 target = curproxy;
5234
5235 if (!target) {
5236 Alert("Proxy '%s': unable to find store table '%s'.\n",
5237 curproxy->id, mrule->table.name);
5238 cfgerr++;
5239 }
5240 else if (target->table.size == 0) {
5241 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5242 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5243 cfgerr++;
5244 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005245 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005246 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5247 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5248 cfgerr++;
5249 }
5250 else {
5251 free((void *)mrule->table.name);
5252 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005253 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005254 }
5255 }
5256
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005257 /* find the target table for 'tcp-request' layer 4 rules */
5258 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5259 struct proxy *target;
5260
Willy Tarreau56123282010-08-06 19:06:56 +02005261 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005262 continue;
5263
5264 if (trule->act_prm.trk_ctr.table.n)
5265 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5266 else
5267 target = curproxy;
5268
5269 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005270 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5271 curproxy->id, trule->act_prm.trk_ctr.table.n,
5272 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005273 cfgerr++;
5274 }
5275 else if (target->table.size == 0) {
5276 Alert("Proxy '%s': table '%s' used but not configured.\n",
5277 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5278 cfgerr++;
5279 }
5280 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005281 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005282 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5283 cfgerr++;
5284 }
5285 else {
5286 free(trule->act_prm.trk_ctr.table.n);
5287 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005288 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005289 * to pass a list of counters to track and allocate them right here using
5290 * stktable_alloc_data_type().
5291 */
5292 }
5293 }
5294
Willy Tarreaud1f96522010-08-03 19:34:32 +02005295 /* find the target table for 'tcp-request' layer 6 rules */
5296 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5297 struct proxy *target;
5298
Willy Tarreau56123282010-08-06 19:06:56 +02005299 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005300 continue;
5301
5302 if (trule->act_prm.trk_ctr.table.n)
5303 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5304 else
5305 target = curproxy;
5306
5307 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005308 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5309 curproxy->id, trule->act_prm.trk_ctr.table.n,
5310 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005311 cfgerr++;
5312 }
5313 else if (target->table.size == 0) {
5314 Alert("Proxy '%s': table '%s' used but not configured.\n",
5315 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5316 cfgerr++;
5317 }
5318 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005319 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02005320 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5321 cfgerr++;
5322 }
5323 else {
5324 free(trule->act_prm.trk_ctr.table.n);
5325 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005326 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005327 * to pass a list of counters to track and allocate them right here using
5328 * stktable_alloc_data_type().
5329 */
5330 }
5331 }
5332
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005333 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5334 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005335 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5336 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5337 "proxy", curproxy->id);
5338 cfgerr++;
5339 goto out_uri_auth_compat;
5340 }
5341
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005342 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005343 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005344 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005345 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005346
Willy Tarreau95fa4692010-02-01 13:05:50 +01005347 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5348 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005349
5350 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005351 uri_auth_compat_req[i++] = "realm";
5352 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5353 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005354
Willy Tarreau95fa4692010-02-01 13:05:50 +01005355 uri_auth_compat_req[i++] = "unless";
5356 uri_auth_compat_req[i++] = "{";
5357 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5358 uri_auth_compat_req[i++] = "}";
5359 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005360
Willy Tarreau95fa4692010-02-01 13:05:50 +01005361 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5362 if (!req_acl) {
5363 cfgerr++;
5364 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005365 }
5366
Willy Tarreau95fa4692010-02-01 13:05:50 +01005367 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5368
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005369 if (curproxy->uri_auth->auth_realm) {
5370 free(curproxy->uri_auth->auth_realm);
5371 curproxy->uri_auth->auth_realm = NULL;
5372 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005373
5374 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005375 }
5376out_uri_auth_compat:
5377
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005378 cfgerr += acl_find_targets(curproxy);
5379
Willy Tarreau2738a142006-07-08 17:28:09 +02005380 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005381 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005382 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005383 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005384 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005385 " | While not properly invalid, you will certainly encounter various problems\n"
5386 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005387 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005388 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005389 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005390 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005391
Willy Tarreau1fa31262007-12-03 00:36:16 +01005392 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5393 * We must still support older configurations, so let's find out whether those
5394 * parameters have been set or must be copied from contimeouts.
5395 */
5396 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005397 if (!curproxy->timeout.tarpit ||
5398 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005399 /* tarpit timeout not set. We search in the following order:
5400 * default.tarpit, curr.connect, default.connect.
5401 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005402 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005403 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005404 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005405 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005406 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005407 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005408 }
5409 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005410 (!curproxy->timeout.queue ||
5411 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005412 /* queue timeout not set. We search in the following order:
5413 * default.queue, curr.connect, default.connect.
5414 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005415 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005416 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005417 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005418 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005419 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005420 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005421 }
5422 }
5423
Willy Tarreau07a54902010-03-29 18:33:29 +02005424 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005425 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5426 curproxy->check_req = (char *)malloc(curproxy->check_len);
5427 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005428 }
5429
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005430 /* The small pools required for the capture lists */
5431 if (curproxy->nb_req_cap)
5432 curproxy->req_cap_pool = create_pool("ptrcap",
5433 curproxy->nb_req_cap * sizeof(char *),
5434 MEM_F_SHARED);
5435 if (curproxy->nb_rsp_cap)
5436 curproxy->rsp_cap_pool = create_pool("ptrcap",
5437 curproxy->nb_rsp_cap * sizeof(char *),
5438 MEM_F_SHARED);
5439
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005440 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5441 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5442 MEM_F_SHARED);
5443
Willy Tarreau86034312006-12-29 00:10:33 +01005444 /* for backwards compatibility with "listen" instances, if
5445 * fullconn is not set but maxconn is set, then maxconn
5446 * is used.
5447 */
5448 if (!curproxy->fullconn)
5449 curproxy->fullconn = curproxy->maxconn;
5450
Willy Tarreaubaaee002006-06-26 02:48:02 +02005451 /* first, we will invert the servers list order */
5452 newsrv = NULL;
5453 while (curproxy->srv) {
5454 struct server *next;
5455
5456 next = curproxy->srv->next;
5457 curproxy->srv->next = newsrv;
5458 newsrv = curproxy->srv;
5459 if (!next)
5460 break;
5461 curproxy->srv = next;
5462 }
5463
Willy Tarreaudd701652010-05-25 23:03:02 +02005464 /* assign automatic UIDs to servers which don't have one yet */
5465 next_id = 1;
5466 newsrv = curproxy->srv;
5467 while (newsrv != NULL) {
5468 if (!newsrv->puid) {
5469 /* server ID not set, use automatic numbering with first
5470 * spare entry starting with next_svid.
5471 */
5472 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5473 newsrv->conf.id.key = newsrv->puid = next_id;
5474 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5475 }
5476 next_id++;
5477 newsrv = newsrv->next;
5478 }
5479
Willy Tarreau20697042007-11-15 23:26:18 +01005480 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005481 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005483 /* We have to initialize the server lookup mechanism depending
5484 * on what LB algorithm was choosen.
5485 */
5486
5487 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5488 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5489 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005490 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5491 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5492 init_server_map(curproxy);
5493 } else {
5494 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5495 fwrr_init_server_groups(curproxy);
5496 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005497 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005498
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005499 case BE_LB_KIND_LC:
5500 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005501 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005502 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005503
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005504 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005505 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5506 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5507 chash_init_server_tree(curproxy);
5508 } else {
5509 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5510 init_server_map(curproxy);
5511 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005512 break;
5513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514
5515 if (curproxy->options & PR_O_LOGASAP)
5516 curproxy->to_log &= ~LW_BYTES;
5517
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005518 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5519 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5520 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5521 proxy_type_str(curproxy), curproxy->id);
5522 err_code |= ERR_WARN;
5523 }
5524
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005525 if (curproxy->mode != PR_MODE_HTTP) {
5526 int optnum;
5527
5528 if (curproxy->options & PR_O_COOK_ANY) {
5529 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5530 proxy_type_str(curproxy), curproxy->id);
5531 err_code |= ERR_WARN;
5532 }
5533
5534 if (curproxy->uri_auth) {
5535 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5536 proxy_type_str(curproxy), curproxy->id);
5537 err_code |= ERR_WARN;
5538 curproxy->uri_auth = NULL;
5539 }
5540
5541 if (curproxy->options & PR_O_FWDFOR) {
5542 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5543 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5544 err_code |= ERR_WARN;
5545 curproxy->options &= ~PR_O_FWDFOR;
5546 }
5547
5548 if (curproxy->options & PR_O_ORGTO) {
5549 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5550 "originalto", proxy_type_str(curproxy), curproxy->id);
5551 err_code |= ERR_WARN;
5552 curproxy->options &= ~PR_O_ORGTO;
5553 }
5554
5555 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5556 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5557 (curproxy->cap & cfg_opts[optnum].cap) &&
5558 (curproxy->options & cfg_opts[optnum].val)) {
5559 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5560 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5561 err_code |= ERR_WARN;
5562 curproxy->options &= ~cfg_opts[optnum].val;
5563 }
5564 }
5565
5566 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5567 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5568 (curproxy->cap & cfg_opts2[optnum].cap) &&
5569 (curproxy->options2 & cfg_opts2[optnum].val)) {
5570 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5571 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5572 err_code |= ERR_WARN;
5573 curproxy->options2 &= ~cfg_opts2[optnum].val;
5574 }
5575 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005576
Willy Tarreauefa5f512010-03-30 20:13:29 +02005577#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005578 if (curproxy->bind_hdr_occ) {
5579 curproxy->bind_hdr_occ = 0;
5580 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5581 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5582 err_code |= ERR_WARN;
5583 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005584#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005585 }
5586
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005588 * ensure that we're not cross-dressing a TCP server into HTTP.
5589 */
5590 newsrv = curproxy->srv;
5591 while (newsrv != NULL) {
5592 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005593 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5594 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005595 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005596 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005597
Willy Tarreauefa5f512010-03-30 20:13:29 +02005598#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005599 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5600 newsrv->bind_hdr_occ = 0;
5601 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5602 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5603 err_code |= ERR_WARN;
5604 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005605#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005606 newsrv = newsrv->next;
5607 }
5608
5609 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 * If this server supports a maxconn parameter, it needs a dedicated
5611 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005612 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 */
5614 newsrv = curproxy->srv;
5615 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005616 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 /* Only 'minconn' was specified, or it was higher than or equal
5618 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5619 * this will avoid further useless expensive computations.
5620 */
5621 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005622 } else if (newsrv->maxconn && !newsrv->minconn) {
5623 /* minconn was not specified, so we set it to maxconn */
5624 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005625 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005626 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5627 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005628 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 }
5630
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005631 if (newsrv->trackit) {
5632 struct proxy *px;
5633 struct server *srv;
5634 char *pname, *sname;
5635
5636 pname = newsrv->trackit;
5637 sname = strrchr(pname, '/');
5638
5639 if (sname)
5640 *sname++ = '\0';
5641 else {
5642 sname = pname;
5643 pname = NULL;
5644 }
5645
5646 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005647 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005648 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005649 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5650 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005651 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005652 cfgerr++;
5653 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005654 }
5655 } else
5656 px = curproxy;
5657
5658 srv = findserver(px, sname);
5659 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005660 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5661 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005662 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005663 cfgerr++;
5664 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005665 }
5666
5667 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005668 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005669 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005670 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005671 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005672 cfgerr++;
5673 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005674 }
5675
5676 if (curproxy != px &&
5677 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005678 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005679 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005680 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005681 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005682 cfgerr++;
5683 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005684 }
5685
5686 newsrv->tracked = srv;
5687 newsrv->tracknext = srv->tracknext;
5688 srv->tracknext = newsrv;
5689
5690 free(newsrv->trackit);
5691 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005692 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 newsrv = newsrv->next;
5694 }
5695
Willy Tarreauc1a21672009-08-16 22:37:44 +02005696 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005697 curproxy->accept = frontend_accept;
5698
Willy Tarreauc1a21672009-08-16 22:37:44 +02005699 if (curproxy->tcp_req.inspect_delay ||
5700 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02005701 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005702
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005703 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005704 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005705 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005706 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005707
5708 /* both TCP and HTTP must check switching rules */
5709 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5710 }
5711
5712 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02005713 if (curproxy->tcp_req.inspect_delay ||
5714 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5715 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
5716
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005717 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005718 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005719 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005720 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005721
5722 /* If the backend does requires RDP cookie persistence, we have to
5723 * enable the corresponding analyser.
5724 */
5725 if (curproxy->options2 & PR_O2_RDPC_PRST)
5726 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5727 }
5728
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005729 listener = NULL;
5730 while (curproxy->listen) {
5731 struct listener *next;
5732
5733 next = curproxy->listen->next;
5734 curproxy->listen->next = listener;
5735 listener = curproxy->listen;
5736
5737 if (!next)
5738 break;
5739
5740 curproxy->listen = next;
5741 }
5742
Willy Tarreaue6b98942007-10-29 01:09:36 +01005743 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005744 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005745 listener = curproxy->listen;
5746 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005747 if (!listener->luid) {
5748 /* listener ID not set, use automatic numbering with first
5749 * spare entry starting with next_luid.
5750 */
5751 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5752 listener->conf.id.key = listener->luid = next_id;
5753 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005754 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005755 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005756
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005757 /* enable separate counters */
5758 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5759 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5760 if (!listener->name) {
5761 sprintf(trash, "sock-%d", listener->luid);
5762 listener->name = strdup(trash);
5763 }
5764 }
5765
Willy Tarreaue6b98942007-10-29 01:09:36 +01005766 if (curproxy->options & PR_O_TCP_NOLING)
5767 listener->options |= LI_O_NOLINGER;
5768 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005769 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005770 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005771 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02005772 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005773 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005774 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005775
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02005776 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
5777 listener->options |= LI_O_TCP_RULES;
5778
Willy Tarreaude3041d2010-05-31 10:56:17 +02005779 if (curproxy->mon_mask.s_addr)
5780 listener->options |= LI_O_CHK_MONNET;
5781
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005782 /* smart accept mode is automatic in HTTP mode */
5783 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5784 (curproxy->mode == PR_MODE_HTTP &&
5785 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5786 listener->options |= LI_O_NOQUICKACK;
5787
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005788 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005789 listener = listener->next;
5790 }
5791
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 curproxy = curproxy->next;
5793 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005794
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005795 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5796 struct auth_users *curuser;
5797 int g;
5798
5799 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5800 unsigned int group_mask = 0;
5801 char *group = NULL;
5802
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005803 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005804 continue;
5805
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005806 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005807
5808 for (g = 0; g < curuserlist->grpcnt; g++)
5809 if (!strcmp(curuserlist->groups[g], group))
5810 break;
5811
5812 if (g == curuserlist->grpcnt) {
5813 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5814 curuserlist->name, group, curuser->user);
5815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
5817 }
5818
5819 group_mask |= (1 << g);
5820 }
5821
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005822 free(curuser->u.groups);
5823 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005824 }
5825
5826 for (g = 0; g < curuserlist->grpcnt; g++) {
5827 char *user = NULL;
5828
5829 if (!curuserlist->groupusers[g])
5830 continue;
5831
5832 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5833 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5834 if (!strcmp(curuser->user, user))
5835 break;
5836
5837 if (!curuser) {
5838 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5839 curuserlist->name, user, curuserlist->groups[g]);
5840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
5842 }
5843
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005844 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005845 }
5846
5847 free(curuserlist->groupusers[g]);
5848 }
5849
5850 free(curuserlist->groupusers);
5851
5852#ifdef DEBUG_AUTH
5853 for (g = 0; g < curuserlist->grpcnt; g++) {
5854 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5855
5856 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5857 if (curuser->group_mask & (1 << g))
5858 fprintf(stderr, " %s", curuser->user);
5859 }
5860
5861 fprintf(stderr, "\n");
5862 }
5863#endif
5864
5865 }
5866
Willy Tarreau056f5682010-06-06 15:51:11 +02005867 /* initialize stick-tables on backend capable proxies. This must not
5868 * be done earlier because the data size may be discovered while parsing
5869 * other proxies.
5870 */
5871 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005872 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02005873
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005874 /*
5875 * Recount currently required checks.
5876 */
5877
5878 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5879 int optnum;
5880
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005881 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5882 if (curproxy->options & cfg_opts[optnum].val)
5883 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005884
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005885 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5886 if (curproxy->options2 & cfg_opts2[optnum].val)
5887 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005888 }
5889
Willy Tarreaubb925012009-07-23 13:36:36 +02005890 if (cfgerr > 0)
5891 err_code |= ERR_ALERT | ERR_FATAL;
5892 out:
5893 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894}
5895
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005896/*
5897 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5898 * parsing sessions.
5899 */
5900void cfg_register_keywords(struct cfg_kw_list *kwl)
5901{
5902 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5903}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005904
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005905/*
5906 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5907 */
5908void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5909{
5910 LIST_DEL(&kwl->list);
5911 LIST_INIT(&kwl->list);
5912}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913
5914/*
5915 * Local variables:
5916 * c-indent-level: 8
5917 * c-basic-offset: 8
5918 * End:
5919 */