blob: 38bd69b5d7d7271e203cd062ae6d94ed28069e9f [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;
Willy Tarreau8a956912010-10-15 14:27:08 +02001313
1314 /* NOTE: the following line might create several listeners if there
1315 * are comma-separated IPs or port ranges. So all further processing
1316 * will have to be applied to all listeners created after last_listen.
1317 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001318 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001322
Willy Tarreau90a570f2009-10-04 20:54:54 +02001323 new_listen = curproxy->listen;
1324 while (new_listen != last_listen) {
1325 new_listen->conf.file = file;
1326 new_listen->conf.line = linenum;
1327 new_listen = new_listen->next;
1328 }
1329
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001330 cur_arg = 2;
1331 while (*(args[cur_arg])) {
1332 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1333#ifdef SO_BINDTODEVICE
1334 struct listener *l;
1335
1336 if (!*args[cur_arg + 1]) {
1337 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001341 }
1342
1343 for (l = curproxy->listen; l != last_listen; l = l->next)
1344 l->interface = strdup(args[cur_arg + 1]);
1345
1346 global.last_checks |= LSTCHK_NETADM;
1347
1348 cur_arg += 2;
1349 continue;
1350#else
1351 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1352 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001355#endif
1356 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001357 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1358#ifdef TCP_MAXSEG
1359 struct listener *l;
1360 int mss;
1361
1362 if (!*args[cur_arg + 1]) {
1363 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1364 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001367 }
1368
1369 mss = str2uic(args[cur_arg + 1]);
1370 if (mss < 1 || mss > 65535) {
1371 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1372 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001373 err_code |= ERR_ALERT | ERR_FATAL;
1374 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001375 }
1376
1377 for (l = curproxy->listen; l != last_listen; l = l->next)
1378 l->maxseg = mss;
1379
1380 cur_arg += 2;
1381 continue;
1382#else
1383 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1384 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001385 err_code |= ERR_ALERT | ERR_FATAL;
1386 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001387#endif
1388 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001389
1390 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1391#ifdef TCP_DEFER_ACCEPT
1392 struct listener *l;
1393
1394 for (l = curproxy->listen; l != last_listen; l = l->next)
1395 l->options |= LI_O_DEF_ACCEPT;
1396
1397 cur_arg ++;
1398 continue;
1399#else
1400 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1401 file, linenum, args[0], args[cur_arg]);
1402 err_code |= ERR_ALERT | ERR_FATAL;
1403 goto out;
1404#endif
1405 }
1406
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001407 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001408#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001409 struct listener *l;
1410
1411 for (l = curproxy->listen; l != last_listen; l = l->next)
1412 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001413
1414 cur_arg ++;
1415 continue;
1416#else
1417 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1418 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001421#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001422 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001423
Willy Tarreau8a956912010-10-15 14:27:08 +02001424 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1425 struct listener *l;
1426
1427 for (l = curproxy->listen; l != last_listen; l = l->next)
1428 l->options |= LI_O_ACC_PROXY;
1429
1430 cur_arg ++;
1431 continue;
1432 }
1433
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001434 if (!strcmp(args[cur_arg], "name")) {
1435 struct listener *l;
1436
1437 for (l = curproxy->listen; l != last_listen; l = l->next)
1438 l->name = strdup(args[cur_arg + 1]);
1439
1440 cur_arg += 2;
1441 continue;
1442 }
1443
1444 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001445 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001446 struct listener *l;
1447
1448 if (curproxy->listen->next != last_listen) {
1449 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1450 file, linenum, args[cur_arg]);
1451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
1453 }
1454
1455 if (!*args[cur_arg + 1]) {
1456 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1457 file, linenum, args[cur_arg]);
1458 err_code |= ERR_ALERT | ERR_FATAL;
1459 goto out;
1460 }
1461
1462 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001463 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001464
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001465 if (curproxy->listen->luid <= 0) {
1466 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001467 file, linenum);
1468 err_code |= ERR_ALERT | ERR_FATAL;
1469 goto out;
1470 }
1471
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001472 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1473 if (node) {
1474 l = container_of(node, struct listener, conf.id);
1475 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1476 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1477 err_code |= ERR_ALERT | ERR_FATAL;
1478 goto out;
1479 }
1480 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1481
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001482 cur_arg += 2;
1483 continue;
1484 }
1485
Willy Tarreau8a956912010-10-15 14:27:08 +02001486 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001487 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001488 err_code |= ERR_ALERT | ERR_FATAL;
1489 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 }
1494 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1495 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1496 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001502 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 /* flush useless bits */
1505 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001508 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001509 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001510 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001511
Willy Tarreau1c47f852006-07-09 08:22:27 +02001512 if (!*args[1]) {
1513 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1514 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001515 err_code |= ERR_ALERT | ERR_FATAL;
1516 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001517 }
1518
Willy Tarreaua534fea2008-08-03 12:19:50 +02001519 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001520 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001521 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001522 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001523 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1524
Willy Tarreau93893792009-07-23 13:19:11 +02001525 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1528 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1529 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1530 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1531 else {
1532 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 }
1536 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001537 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001538 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001539
1540 if (curproxy == &defproxy) {
1541 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001545 }
1546
1547 if (!*args[1]) {
1548 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001552 }
1553
1554 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001555 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001556
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001557 if (curproxy->uuid <= 0) {
1558 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001559 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001560 err_code |= ERR_ALERT | ERR_FATAL;
1561 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001562 }
1563
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001564 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1565 if (node) {
1566 struct proxy *target = container_of(node, struct proxy, conf.id);
1567 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1568 file, linenum, proxy_type_str(curproxy), curproxy->id,
1569 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
1572 }
1573 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001574 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001575 else if (!strcmp(args[0], "description")) {
1576 int i, len=0;
1577 char *d;
1578
Cyril Bonté99ed3272010-01-24 23:29:44 +01001579 if (curproxy == &defproxy) {
1580 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1581 file, linenum, args[0]);
1582 err_code |= ERR_ALERT | ERR_FATAL;
1583 goto out;
1584 }
1585
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001586 if (!*args[1]) {
1587 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1588 file, linenum, args[0]);
1589 return -1;
1590 }
1591
1592 for(i=1; *args[i]; i++)
1593 len += strlen(args[i])+1;
1594
1595 d = (char *)calloc(1, len);
1596 curproxy->desc = d;
1597
1598 d += sprintf(d, "%s", args[1]);
1599 for(i=2; *args[i]; i++)
1600 d += sprintf(d, " %s", args[i]);
1601
1602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1604 curproxy->state = PR_STSTOPPED;
1605 }
1606 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1607 curproxy->state = PR_STNEW;
1608 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001609 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1610 int cur_arg = 1;
1611 unsigned int set = 0;
1612
1613 while (*args[cur_arg]) {
1614 int u;
1615 if (strcmp(args[cur_arg], "all") == 0) {
1616 set = 0;
1617 break;
1618 }
1619 else if (strcmp(args[cur_arg], "odd") == 0) {
1620 set |= 0x55555555;
1621 }
1622 else if (strcmp(args[cur_arg], "even") == 0) {
1623 set |= 0xAAAAAAAA;
1624 }
1625 else {
1626 u = str2uic(args[cur_arg]);
1627 if (u < 1 || u > 32) {
1628 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001632 }
1633 if (u > global.nbproc) {
1634 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001637 }
1638 set |= 1 << (u - 1);
1639 }
1640 cur_arg++;
1641 }
1642 curproxy->bind_proc = set;
1643 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001644 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001645 if (curproxy == &defproxy) {
1646 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001647 err_code |= ERR_ALERT | ERR_FATAL;
1648 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001649 }
1650
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001651 err = invalid_char(args[1]);
1652 if (err) {
1653 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1654 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001655 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001656 }
1657
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001658 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1659 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1660 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
1662 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001663 }
1664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1666 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667
Willy Tarreau977b8e42006-12-29 14:19:17 +01001668 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001669 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001670
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 if (*(args[1]) == 0) {
1672 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1673 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001677
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001678 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001679 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001680 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001681 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001682 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 curproxy->cookie_name = strdup(args[1]);
1684 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 cur_arg = 2;
1687 while (*(args[cur_arg])) {
1688 if (!strcmp(args[cur_arg], "rewrite")) {
1689 curproxy->options |= PR_O_COOK_RW;
1690 }
1691 else if (!strcmp(args[cur_arg], "indirect")) {
1692 curproxy->options |= PR_O_COOK_IND;
1693 }
1694 else if (!strcmp(args[cur_arg], "insert")) {
1695 curproxy->options |= PR_O_COOK_INS;
1696 }
1697 else if (!strcmp(args[cur_arg], "nocache")) {
1698 curproxy->options |= PR_O_COOK_NOC;
1699 }
1700 else if (!strcmp(args[cur_arg], "postonly")) {
1701 curproxy->options |= PR_O_COOK_POST;
1702 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001703 else if (!strcmp(args[cur_arg], "preserve")) {
1704 curproxy->options2 |= PR_O2_COOK_PSV;
1705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 else if (!strcmp(args[cur_arg], "prefix")) {
1707 curproxy->options |= PR_O_COOK_PFX;
1708 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001709 else if (!strcmp(args[cur_arg], "domain")) {
1710 if (!*args[cur_arg + 1]) {
1711 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1712 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001713 err_code |= ERR_ALERT | ERR_FATAL;
1714 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001715 }
1716
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001717 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001718 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001719 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1720 " dots nor does not start with a dot."
1721 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001722 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001723 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001724 }
1725
1726 err = invalid_domainchar(args[cur_arg + 1]);
1727 if (err) {
1728 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1729 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001732 }
1733
Willy Tarreau68a897b2009-12-03 23:28:34 +01001734 if (!curproxy->cookie_domain) {
1735 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1736 } else {
1737 /* one domain was already specified, add another one by
1738 * building the string which will be returned along with
1739 * the cookie.
1740 */
1741 char *new_ptr;
1742 int new_len = strlen(curproxy->cookie_domain) +
1743 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1744 new_ptr = malloc(new_len);
1745 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1746 free(curproxy->cookie_domain);
1747 curproxy->cookie_domain = new_ptr;
1748 }
Willy Tarreau31936852010-10-06 16:59:56 +02001749 cur_arg++;
1750 }
1751 else if (!strcmp(args[cur_arg], "maxidle")) {
1752 unsigned int maxidle;
1753 const char *res;
1754
1755 if (!*args[cur_arg + 1]) {
1756 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
1757 file, linenum, args[cur_arg]);
1758 err_code |= ERR_ALERT | ERR_FATAL;
1759 goto out;
1760 }
1761
1762 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
1763 if (res) {
1764 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
1765 file, linenum, *res, args[cur_arg]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
1768 }
1769 curproxy->cookie_maxidle = maxidle;
1770 cur_arg++;
1771 }
1772 else if (!strcmp(args[cur_arg], "maxlife")) {
1773 unsigned int maxlife;
1774 const char *res;
1775
1776 if (!*args[cur_arg + 1]) {
1777 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
1778 file, linenum, args[cur_arg]);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782
1783 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
1784 if (res) {
1785 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
1786 file, linenum, *res, args[cur_arg]);
1787 err_code |= ERR_ALERT | ERR_FATAL;
1788 goto out;
1789 }
1790 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001791 cur_arg++;
1792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 else {
Willy Tarreau31936852010-10-06 16:59:56 +02001794 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 +02001795 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798 }
1799 cur_arg++;
1800 }
1801 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1802 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1803 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001804 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805 }
1806
1807 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1808 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1809 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001810 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001812
1813 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
1814 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
1815 file, linenum);
1816 err_code |= ERR_ALERT | ERR_FATAL;
1817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001819 else if (!strcmp(args[0], "persist")) { /* persist */
1820 if (*(args[1]) == 0) {
1821 Alert("parsing [%s:%d] : missing persist method.\n",
1822 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001825 }
1826
1827 if (!strncmp(args[1], "rdp-cookie", 10)) {
1828 curproxy->options2 |= PR_O2_RDPC_PRST;
1829
Emeric Brunb982a3d2010-01-04 15:45:53 +01001830 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001831 const char *beg, *end;
1832
1833 beg = args[1] + 11;
1834 end = strchr(beg, ')');
1835
1836 if (!end || end == beg) {
1837 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1838 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001841 }
1842
1843 free(curproxy->rdp_cookie_name);
1844 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1845 curproxy->rdp_cookie_len = end-beg;
1846 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001847 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001848 free(curproxy->rdp_cookie_name);
1849 curproxy->rdp_cookie_name = strdup("msts");
1850 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1851 }
1852 else { /* syntax */
1853 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1854 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001857 }
1858 }
1859 else {
1860 Alert("parsing [%s:%d] : unknown persist method.\n",
1861 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001864 }
1865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001867 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001869 if (curproxy == &defproxy) {
1870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
1873 }
1874
Willy Tarreau977b8e42006-12-29 14:19:17 +01001875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001876 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001877
Willy Tarreaubaaee002006-06-26 02:48:02 +02001878 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001879 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001881 err_code |= ERR_ALERT | ERR_FATAL;
1882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 }
1884 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001885 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 curproxy->appsession_name = strdup(args[1]);
1887 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1888 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001889 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1890 if (err) {
1891 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1892 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001895 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001896 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001897
Willy Tarreau51041c72007-09-09 21:56:53 +02001898 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1899 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001900 err_code |= ERR_ALERT | ERR_ABORT;
1901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001903
1904 cur_arg = 6;
1905 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001906 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1907 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001908 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001909 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001910 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001911 } else if (!strcmp(args[cur_arg], "prefix")) {
1912 curproxy->options2 |= PR_O2_AS_PFX;
1913 } else if (!strcmp(args[cur_arg], "mode")) {
1914 if (!*args[cur_arg + 1]) {
1915 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1916 file, linenum, args[0], args[cur_arg]);
1917 err_code |= ERR_ALERT | ERR_FATAL;
1918 goto out;
1919 }
1920
1921 cur_arg++;
1922 if (!strcmp(args[cur_arg], "query-string")) {
1923 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1924 curproxy->options2 |= PR_O2_AS_M_QS;
1925 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1926 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1927 curproxy->options2 |= PR_O2_AS_M_PP;
1928 } else {
1929 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
1932 }
1933 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001934 cur_arg++;
1935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 } /* Url App Session */
1937 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001938 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001942 if (curproxy == &defproxy) {
1943 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
1946 }
1947
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948 if (*(args[4]) == 0) {
1949 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1950 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_ALERT | ERR_FATAL;
1952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001954 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 curproxy->capture_name = strdup(args[2]);
1956 curproxy->capture_namelen = strlen(curproxy->capture_name);
1957 curproxy->capture_len = atol(args[4]);
1958 if (curproxy->capture_len >= CAPTURE_LEN) {
1959 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1960 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 curproxy->capture_len = CAPTURE_LEN - 1;
1963 }
1964 curproxy->to_log |= LW_COOKIE;
1965 }
1966 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1967 struct cap_hdr *hdr;
1968
1969 if (curproxy == &defproxy) {
1970 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 +02001971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 }
1974
1975 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1976 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1977 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980 }
1981
1982 hdr = calloc(sizeof(struct cap_hdr), 1);
1983 hdr->next = curproxy->req_cap;
1984 hdr->name = strdup(args[3]);
1985 hdr->namelen = strlen(args[3]);
1986 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001987 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 hdr->index = curproxy->nb_req_cap++;
1989 curproxy->req_cap = hdr;
1990 curproxy->to_log |= LW_REQHDR;
1991 }
1992 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1993 struct cap_hdr *hdr;
1994
1995 if (curproxy == &defproxy) {
1996 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 +02001997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 }
2000
2001 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2002 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2003 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002004 err_code |= ERR_ALERT | ERR_FATAL;
2005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002006 }
2007 hdr = calloc(sizeof(struct cap_hdr), 1);
2008 hdr->next = curproxy->rsp_cap;
2009 hdr->name = strdup(args[3]);
2010 hdr->namelen = strlen(args[3]);
2011 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002012 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 hdr->index = curproxy->nb_rsp_cap++;
2014 curproxy->rsp_cap = hdr;
2015 curproxy->to_log |= LW_RSPHDR;
2016 }
2017 else {
2018 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 }
2023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002025 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002027
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 if (*(args[1]) == 0) {
2029 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 }
2034 curproxy->conn_retries = atol(args[1]);
2035 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002036 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2037 struct req_acl_rule *req_acl;
2038
2039 if (curproxy == &defproxy) {
2040 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
2043 }
2044
2045
2046 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2047 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2048 file, linenum, args[0]);
2049 err_code |= ERR_WARN;
2050 }
2051
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002052 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002053
2054 if (!req_acl) {
2055 err_code |= ERR_ALERT | ERR_ABORT;
2056 goto out;
2057 }
2058
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002059 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002060 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2061 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002062 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002063 if (curproxy == &defproxy) {
2064 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002067 }
2068
Willy Tarreauef6494c2010-01-28 17:12:36 +01002069 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002070 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002074 }
2075
Willy Tarreauef6494c2010-01-28 17:12:36 +01002076 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002077 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2078 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002081 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002082
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002083 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002084 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002085 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002086 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002087 struct redirect_rule *rule;
2088 int cur_arg;
2089 int type = REDIRECT_TYPE_NONE;
2090 int code = 302;
2091 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002092 char *cookie = NULL;
2093 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002094 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002095
Cyril Bonté99ed3272010-01-24 23:29:44 +01002096 if (curproxy == &defproxy) {
2097 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
2100 }
2101
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002102 cur_arg = 1;
2103 while (*(args[cur_arg])) {
2104 if (!strcmp(args[cur_arg], "location")) {
2105 if (!*args[cur_arg + 1]) {
2106 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2107 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002110 }
2111
2112 type = REDIRECT_TYPE_LOCATION;
2113 cur_arg++;
2114 destination = args[cur_arg];
2115 }
2116 else if (!strcmp(args[cur_arg], "prefix")) {
2117 if (!*args[cur_arg + 1]) {
2118 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2119 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002122 }
2123
2124 type = REDIRECT_TYPE_PREFIX;
2125 cur_arg++;
2126 destination = args[cur_arg];
2127 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002128 else if (!strcmp(args[cur_arg], "set-cookie")) {
2129 if (!*args[cur_arg + 1]) {
2130 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2131 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002134 }
2135
2136 cur_arg++;
2137 cookie = args[cur_arg];
2138 cookie_set = 1;
2139 }
2140 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2141 if (!*args[cur_arg + 1]) {
2142 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2143 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002146 }
2147
2148 cur_arg++;
2149 cookie = args[cur_arg];
2150 cookie_set = 0;
2151 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002152 else if (!strcmp(args[cur_arg],"code")) {
2153 if (!*args[cur_arg + 1]) {
2154 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002156 err_code |= ERR_ALERT | ERR_FATAL;
2157 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002158 }
2159 cur_arg++;
2160 code = atol(args[cur_arg]);
2161 if (code < 301 || code > 303) {
2162 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2163 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002166 }
2167 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002168 else if (!strcmp(args[cur_arg],"drop-query")) {
2169 flags |= REDIRECT_FLAG_DROP_QS;
2170 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002171 else if (!strcmp(args[cur_arg],"append-slash")) {
2172 flags |= REDIRECT_FLAG_APPEND_SLASH;
2173 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002174 else if (strcmp(args[cur_arg], "if") == 0 ||
2175 strcmp(args[cur_arg], "unless") == 0) {
2176 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2177 if (!cond) {
2178 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2179 file, linenum, args[0]);
2180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
2182 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002183 break;
2184 }
2185 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002186 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 +02002187 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002190 }
2191 cur_arg++;
2192 }
2193
2194 if (type == REDIRECT_TYPE_NONE) {
2195 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002199 }
2200
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002201 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2202 rule->cond = cond;
2203 rule->rdr_str = strdup(destination);
2204 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002205 if (cookie) {
2206 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002207 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002208 */
2209 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002210 if (cookie_set) {
2211 rule->cookie_str = malloc(rule->cookie_len + 10);
2212 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2213 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2214 rule->cookie_len += 9;
2215 } else {
2216 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002217 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002218 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2219 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002220 }
2221 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002222 rule->type = type;
2223 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002224 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002225 LIST_INIT(&rule->list);
2226 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002227 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002228 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002229 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002230 struct switching_rule *rule;
2231
Willy Tarreaub099aca2008-10-12 17:26:37 +02002232 if (curproxy == &defproxy) {
2233 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002236 }
2237
Willy Tarreau55ea7572007-06-17 19:56:27 +02002238 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002240
2241 if (*(args[1]) == 0) {
2242 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002245 }
2246
Willy Tarreauef6494c2010-01-28 17:12:36 +01002247 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002248 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2249 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002252 }
2253
Willy Tarreauef6494c2010-01-28 17:12:36 +01002254 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002255 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002256 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002259 }
2260
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002261 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002262
Willy Tarreau55ea7572007-06-17 19:56:27 +02002263 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2264 rule->cond = cond;
2265 rule->be.name = strdup(args[1]);
2266 LIST_INIT(&rule->list);
2267 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2268 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002269 else if ((!strcmp(args[0], "force-persist")) ||
2270 (!strcmp(args[0], "ignore-persist"))) {
2271 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002272
2273 if (curproxy == &defproxy) {
2274 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
2277 }
2278
2279 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2280 err_code |= ERR_WARN;
2281
Willy Tarreauef6494c2010-01-28 17:12:36 +01002282 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002283 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2284 file, linenum, args[0]);
2285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
2287 }
2288
Willy Tarreauef6494c2010-01-28 17:12:36 +01002289 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002290 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2291 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
2294 }
2295
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002296 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002297
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002298 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002299 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002300 if (!strcmp(args[0], "force-persist")) {
2301 rule->type = PERSIST_TYPE_FORCE;
2302 } else {
2303 rule->type = PERSIST_TYPE_IGNORE;
2304 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002305 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002306 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002307 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002308 else if (!strcmp(args[0], "stick-table")) {
2309 int myidx = 1;
2310
2311 curproxy->table.type = (unsigned int)-1;
2312 while (*args[myidx]) {
2313 const char *err;
2314
2315 if (strcmp(args[myidx], "size") == 0) {
2316 myidx++;
2317 if (!*(args[myidx])) {
2318 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2319 file, linenum, args[myidx-1]);
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2324 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2325 file, linenum, *err, args[myidx-1]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002329 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002330 }
2331 else if (strcmp(args[myidx], "expire") == 0) {
2332 myidx++;
2333 if (!*(args[myidx])) {
2334 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2335 file, linenum, args[myidx-1]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2340 if (err) {
2341 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2342 file, linenum, *err, args[myidx-1]);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002347 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002348 }
2349 else if (strcmp(args[myidx], "nopurge") == 0) {
2350 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002351 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002352 }
2353 else if (strcmp(args[myidx], "type") == 0) {
2354 myidx++;
2355 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2356 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2357 file, linenum, args[myidx]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002361 /* myidx already points to next arg */
2362 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002363 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002364 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002365 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002366
2367 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002368 nw = args[myidx];
2369 while (*nw) {
2370 /* the "store" keyword supports a comma-separated list */
2371 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002372 sa = NULL; /* store arg */
2373 while (*nw && *nw != ',') {
2374 if (*nw == '(') {
2375 *nw = 0;
2376 sa = ++nw;
2377 while (*nw != ')') {
2378 if (!*nw) {
2379 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2380 file, linenum, args[0], cw);
2381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
2383 }
2384 nw++;
2385 }
2386 *nw = '\0';
2387 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002388 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002389 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002390 if (*nw)
2391 *nw++ = '\0';
2392 type = stktable_get_data_type(cw);
2393 if (type < 0) {
2394 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2395 file, linenum, args[0], cw);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
2398 }
Willy Tarreauac782882010-06-20 10:41:54 +02002399
2400 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2401 switch (err) {
2402 case PE_NONE: break;
2403 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002404 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2405 file, linenum, args[0], cw);
2406 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002407 break;
2408
2409 case PE_ARG_MISSING:
2410 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2411 file, linenum, args[0], cw);
2412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
2414
2415 case PE_ARG_NOT_USED:
2416 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2417 file, linenum, args[0], cw);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420
2421 default:
2422 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2423 file, linenum, args[0], cw);
2424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002426 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002427 }
2428 myidx++;
2429 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002430 else {
2431 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2432 file, linenum, args[myidx]);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002435 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002436 }
2437
2438 if (!curproxy->table.size) {
2439 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2440 file, linenum);
2441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
2443 }
2444
2445 if (curproxy->table.type == (unsigned int)-1) {
2446 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2447 file, linenum);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451 }
2452 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002453 struct sticking_rule *rule;
2454 struct pattern_expr *expr;
2455 int myidx = 0;
2456 const char *name = NULL;
2457 int flags;
2458
2459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
2465 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2466 err_code |= ERR_WARN;
2467 goto out;
2468 }
2469
2470 myidx++;
2471 if ((strcmp(args[myidx], "store") == 0) ||
2472 (strcmp(args[myidx], "store-request") == 0)) {
2473 myidx++;
2474 flags = STK_IS_STORE;
2475 }
2476 else if (strcmp(args[myidx], "store-response") == 0) {
2477 myidx++;
2478 flags = STK_IS_STORE | STK_ON_RSP;
2479 }
2480 else if (strcmp(args[myidx], "match") == 0) {
2481 myidx++;
2482 flags = STK_IS_MATCH;
2483 }
2484 else if (strcmp(args[myidx], "on") == 0) {
2485 myidx++;
2486 flags = STK_IS_MATCH | STK_IS_STORE;
2487 }
2488 else {
2489 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493
2494 if (*(args[myidx]) == 0) {
2495 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
2498 }
2499
2500 expr = pattern_parse_expr(args, &myidx);
2501 if (!expr) {
2502 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506
2507 if (flags & STK_ON_RSP) {
2508 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2509 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2510 file, linenum, args[0], expr->fetch->kw);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514 } else {
2515 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2516 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2517 file, linenum, args[0], expr->fetch->kw);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521 }
2522
2523 if (strcmp(args[myidx], "table") == 0) {
2524 myidx++;
2525 name = args[myidx++];
2526 }
2527
Willy Tarreauef6494c2010-01-28 17:12:36 +01002528 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2529 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002530 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2531 file, linenum, args[0]);
2532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
2534 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002535 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002536 else if (*(args[myidx])) {
2537 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2538 file, linenum, args[0], args[myidx]);
2539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
2541 }
2542
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002543 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2544
Emeric Brunb982a3d2010-01-04 15:45:53 +01002545 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2546 rule->cond = cond;
2547 rule->expr = expr;
2548 rule->flags = flags;
2549 rule->table.name = name ? strdup(name) : NULL;
2550 LIST_INIT(&rule->list);
2551 if (flags & STK_ON_RSP)
2552 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2553 else
2554 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002559
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2561 curproxy->uri_auth = NULL; /* we must detach from the default config */
2562
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002563 if (!*args[1]) {
2564 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002565 } else if (!strcmp(args[1], "admin")) {
2566 struct stats_admin_rule *rule;
2567
2568 if (curproxy == &defproxy) {
2569 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
2572 }
2573
2574 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2575 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2576 err_code |= ERR_ALERT | ERR_ABORT;
2577 goto out;
2578 }
2579
2580 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2581 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2582 file, linenum, args[0], args[1]);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
2585 }
2586 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2587 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2588 file, linenum, args[0], args[1]);
2589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
2591 }
2592
2593 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2594
2595 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2596 rule->cond = cond;
2597 LIST_INIT(&rule->list);
2598 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 } else if (!strcmp(args[1], "uri")) {
2600 if (*(args[2]) == 0) {
2601 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2605 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_ABORT;
2607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 }
2609 } else if (!strcmp(args[1], "realm")) {
2610 if (*(args[2]) == 0) {
2611 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2615 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_ALERT | ERR_ABORT;
2617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002619 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002620 unsigned interval;
2621
2622 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2623 if (err) {
2624 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2625 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002628 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2629 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_ABORT;
2631 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002632 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002633 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2634 struct req_acl_rule *req_acl;
2635
2636 if (curproxy == &defproxy) {
2637 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
2641
2642 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2643 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2644 err_code |= ERR_ALERT | ERR_ABORT;
2645 goto out;
2646 }
2647
2648 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2649 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2650 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2651 file, linenum, args[0]);
2652 err_code |= ERR_WARN;
2653 }
2654
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002655 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002656
2657 if (!req_acl) {
2658 err_code |= ERR_ALERT | ERR_ABORT;
2659 goto out;
2660 }
2661
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002662 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002663 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2664
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 } else if (!strcmp(args[1], "auth")) {
2666 if (*(args[2]) == 0) {
2667 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2671 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002672 err_code |= ERR_ALERT | ERR_ABORT;
2673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 }
2675 } else if (!strcmp(args[1], "scope")) {
2676 if (*(args[2]) == 0) {
2677 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2681 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_ALERT | ERR_ABORT;
2683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
2685 } else if (!strcmp(args[1], "enable")) {
2686 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2687 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_ABORT;
2689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002691 } else if (!strcmp(args[1], "hide-version")) {
2692 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2693 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_ABORT;
2695 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002696 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002697 } else if (!strcmp(args[1], "show-legends")) {
2698 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2699 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2700 err_code |= ERR_ALERT | ERR_ABORT;
2701 goto out;
2702 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002703 } else if (!strcmp(args[1], "show-node")) {
2704
2705 if (*args[2]) {
2706 int i;
2707 char c;
2708
2709 for (i=0; args[2][i]; i++) {
2710 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002711 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2712 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002713 break;
2714 }
2715
2716 if (!i || args[2][i]) {
2717 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2718 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2719 file, linenum, args[0], args[1]);
2720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
2722 }
2723 }
2724
2725 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2726 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2727 err_code |= ERR_ALERT | ERR_ABORT;
2728 goto out;
2729 }
2730 } else if (!strcmp(args[1], "show-desc")) {
2731 char *desc = NULL;
2732
2733 if (*args[2]) {
2734 int i, len=0;
2735 char *d;
2736
2737 for(i=2; *args[i]; i++)
2738 len += strlen(args[i])+1;
2739
2740 desc = d = (char *)calloc(1, len);
2741
2742 d += sprintf(d, "%s", args[2]);
2743 for(i=3; *args[i]; i++)
2744 d += sprintf(d, " %s", args[i]);
2745 }
2746
2747 if (!*args[2] && !global.desc)
2748 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2749 file, linenum, args[1]);
2750 else {
2751 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2752 free(desc);
2753 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2754 err_code |= ERR_ALERT | ERR_ABORT;
2755 goto out;
2756 }
2757 free(desc);
2758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002760stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02002761 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 +01002762 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 }
2766 }
2767 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002768 int optnum;
2769
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002770 if (*(args[1]) == '\0') {
2771 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002776
2777 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2778 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002779 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2780 err_code |= ERR_WARN;
2781 goto out;
2782 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002783
Willy Tarreau3842f002009-06-14 11:39:52 +02002784 curproxy->no_options &= ~cfg_opts[optnum].val;
2785 curproxy->options &= ~cfg_opts[optnum].val;
2786
2787 switch (kwm) {
2788 case KWM_STD:
2789 curproxy->options |= cfg_opts[optnum].val;
2790 break;
2791 case KWM_NO:
2792 curproxy->no_options |= cfg_opts[optnum].val;
2793 break;
2794 case KWM_DEF: /* already cleared */
2795 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002796 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002797
Willy Tarreau93893792009-07-23 13:19:11 +02002798 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002799 }
2800 }
2801
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002802 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2803 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002804 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2805 err_code |= ERR_WARN;
2806 goto out;
2807 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002808
Willy Tarreau3842f002009-06-14 11:39:52 +02002809 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2810 curproxy->options2 &= ~cfg_opts2[optnum].val;
2811
2812 switch (kwm) {
2813 case KWM_STD:
2814 curproxy->options2 |= cfg_opts2[optnum].val;
2815 break;
2816 case KWM_NO:
2817 curproxy->no_options2 |= cfg_opts2[optnum].val;
2818 break;
2819 case KWM_DEF: /* already cleared */
2820 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002821 }
Willy Tarreau93893792009-07-23 13:19:11 +02002822 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002823 }
2824 }
2825
Willy Tarreau3842f002009-06-14 11:39:52 +02002826 if (kwm != KWM_STD) {
2827 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002828 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002831 }
2832
Emeric Brun3a058f32009-06-30 18:26:00 +02002833 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002835 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002837 if (*(args[2]) != '\0') {
2838 if (!strcmp(args[2], "clf")) {
2839 curproxy->options2 |= PR_O2_CLFLOG;
2840 } else {
2841 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002844 }
2845 }
2846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 else if (!strcmp(args[1], "tcplog"))
2848 /* generate a detailed TCP log */
2849 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 else if (!strcmp(args[1], "tcpka")) {
2851 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002852 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002854
2855 if (curproxy->cap & PR_CAP_FE)
2856 curproxy->options |= PR_O_TCP_CLI_KA;
2857 if (curproxy->cap & PR_CAP_BE)
2858 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859 }
2860 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002861 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_WARN;
2863
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002865 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002866 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002867 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002868 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002869 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002870 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002871 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 if (!*args[2]) { /* no argument */
2873 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2874 curproxy->check_len = strlen(DEF_CHECK_REQ);
2875 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002876 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 curproxy->check_req = (char *)malloc(reqlen);
2878 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002879 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002881 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 if (*args[4])
2883 reqlen += strlen(args[4]);
2884 else
2885 reqlen += strlen("HTTP/1.0");
2886
2887 curproxy->check_req = (char *)malloc(reqlen);
2888 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002889 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002891 }
2892 else if (!strcmp(args[1], "ssl-hello-chk")) {
2893 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002894 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002896
Willy Tarreaua534fea2008-08-03 12:19:50 +02002897 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002898 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002899 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002900 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002901 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002902 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002903 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 }
Willy Tarreau23677902007-05-08 23:50:35 +02002905 else if (!strcmp(args[1], "smtpchk")) {
2906 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002907 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002908 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002909 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002910 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002911 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002912 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002913 curproxy->options |= PR_O_SMTP_CHK;
2914
2915 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2916 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2917 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2918 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2919 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2920 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2921 curproxy->check_req = (char *)malloc(reqlen);
2922 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2923 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2924 } else {
2925 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2926 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2927 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2928 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2929 }
2930 }
2931 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002932 else if (!strcmp(args[1], "mysql-check")) {
2933 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02002934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
2935 err_code |= ERR_WARN;
2936
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002937 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002938 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002939 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002940 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002941 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02002942 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002943 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02002944
2945 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
2946 * const char mysql40_client_auth_pkt[] = {
2947 * "\x0e\x00\x00" // packet length
2948 * "\x01" // packet number
2949 * "\x00\x00" // client capabilities
2950 * "\x00\x00\x01" // max packet
2951 * "haproxy\x00" // username (null terminated string)
2952 * "\x00" // filler (always 0x00)
2953 * "\x01\x00\x00" // packet length
2954 * "\x00" // packet number
2955 * "\x01" // COM_QUIT command
2956 * };
2957 */
2958
2959 if (*(args[2])) {
2960 int cur_arg = 2;
2961
2962 while (*(args[cur_arg])) {
2963 if (strcmp(args[cur_arg], "user") == 0) {
2964 char *mysqluser;
2965 int packetlen, reqlen, userlen;
2966
2967 /* suboption header - needs additional argument for it */
2968 if (*(args[cur_arg+1]) == 0) {
2969 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
2970 file, linenum, args[0], args[1], args[cur_arg]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974 mysqluser = args[cur_arg + 1];
2975 userlen = strlen(mysqluser);
2976 packetlen = userlen + 7;
2977 reqlen = packetlen + 9;
2978
2979 free(curproxy->check_req);
2980 curproxy->check_req = (char *)calloc(1, reqlen);
2981 curproxy->check_len = reqlen;
2982
2983 snprintf(curproxy->check_req, 4, "%c%c%c",
2984 ((unsigned char) packetlen & 0xff),
2985 ((unsigned char) (packetlen >> 8) & 0xff),
2986 ((unsigned char) (packetlen >> 16) & 0xff));
2987
2988 curproxy->check_req[3] = 1;
2989 curproxy->check_req[8] = 1;
2990 memcpy(&curproxy->check_req[9], mysqluser, userlen);
2991 curproxy->check_req[9 + userlen + 1 + 1] = 1;
2992 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
2993 cur_arg += 2;
2994 } else {
2995 /* unknown suboption - catchall */
2996 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
2997 file, linenum, args[0], args[1]);
2998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
3000 }
3001 } /* end while loop */
3002 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003003 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003004 else if (!strcmp(args[1], "ldap-check")) {
3005 /* use LDAP request to check servers' health */
3006 free(curproxy->check_req);
3007 curproxy->check_req = NULL;
3008 curproxy->options &= ~PR_O_HTTP_CHK;
3009 curproxy->options &= ~PR_O_SMTP_CHK;
3010 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3011 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3012 curproxy->options2 |= PR_O2_LDAP_CHK;
3013
3014 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3015 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3016 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3017 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003018 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003019 int cur_arg;
3020
3021 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3022 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003023 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003024
3025 curproxy->options |= PR_O_FWDFOR;
3026
3027 free(curproxy->fwdfor_hdr_name);
3028 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3029 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3030
3031 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3032 cur_arg = 2;
3033 while (*(args[cur_arg])) {
3034 if (!strcmp(args[cur_arg], "except")) {
3035 /* suboption except - needs additional argument for it */
3036 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3037 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3038 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003041 }
3042 /* flush useless bits */
3043 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003044 cur_arg += 2;
3045 } else if (!strcmp(args[cur_arg], "header")) {
3046 /* suboption header - needs additional argument for it */
3047 if (*(args[cur_arg+1]) == 0) {
3048 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3049 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003052 }
3053 free(curproxy->fwdfor_hdr_name);
3054 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3055 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3056 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003057 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003058 /* unknown suboption - catchall */
3059 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3060 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003063 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003064 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003065 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003066 else if (!strcmp(args[1], "originalto")) {
3067 int cur_arg;
3068
3069 /* insert x-original-to field, but not for the IP address listed as an except.
3070 * set default options (ie: bitfield, header name, etc)
3071 */
3072
3073 curproxy->options |= PR_O_ORGTO;
3074
3075 free(curproxy->orgto_hdr_name);
3076 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3077 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3078
3079 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3080 cur_arg = 2;
3081 while (*(args[cur_arg])) {
3082 if (!strcmp(args[cur_arg], "except")) {
3083 /* suboption except - needs additional argument for it */
3084 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3085 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3086 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_FATAL;
3088 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003089 }
3090 /* flush useless bits */
3091 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3092 cur_arg += 2;
3093 } else if (!strcmp(args[cur_arg], "header")) {
3094 /* suboption header - needs additional argument for it */
3095 if (*(args[cur_arg+1]) == 0) {
3096 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3097 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003100 }
3101 free(curproxy->orgto_hdr_name);
3102 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3103 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3104 cur_arg += 2;
3105 } else {
3106 /* unknown suboption - catchall */
3107 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3108 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003111 }
3112 } /* end while loop */
3113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 else {
3115 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 }
Willy Tarreau93893792009-07-23 13:19:11 +02003119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003121 else if (!strcmp(args[0], "default_backend")) {
3122 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003124
3125 if (*(args[1]) == 0) {
3126 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003129 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003130 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003131 curproxy->defbe.name = strdup(args[1]);
3132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003134 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003135 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003136
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003137 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3138 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 /* enable reconnections to dispatch */
3141 curproxy->options |= PR_O_REDISP;
3142 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003143 else if (!strcmp(args[0], "http-check")) {
3144 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003146
3147 if (strcmp(args[1], "disable-on-404") == 0) {
3148 /* enable a graceful server shutdown on an HTTP 404 response */
3149 curproxy->options |= PR_O_DISABLE404;
3150 }
Willy Tarreauef781042010-01-27 11:53:01 +01003151 else if (strcmp(args[1], "send-state") == 0) {
3152 /* enable emission of the apparent state of a server in HTTP checks */
3153 curproxy->options2 |= PR_O2_CHK_SNDST;
3154 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003155 else if (strcmp(args[1], "expect") == 0) {
3156 const char *ptr_arg;
3157 int cur_arg;
3158
3159 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3160 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164
3165 cur_arg = 2;
3166 /* consider exclamation marks, sole or at the beginning of a word */
3167 while (*(ptr_arg = args[cur_arg])) {
3168 while (*ptr_arg == '!') {
3169 curproxy->options2 ^= PR_O2_EXP_INV;
3170 ptr_arg++;
3171 }
3172 if (*ptr_arg)
3173 break;
3174 cur_arg++;
3175 }
3176 /* now ptr_arg points to the beginning of a word past any possible
3177 * exclamation mark, and cur_arg is the argument which holds this word.
3178 */
3179 if (strcmp(ptr_arg, "status") == 0) {
3180 if (!*(args[cur_arg + 1])) {
3181 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3182 file, linenum, args[0], args[1], ptr_arg);
3183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
3185 }
3186 curproxy->options2 |= PR_O2_EXP_STS;
3187 curproxy->expect_str = strdup(args[cur_arg + 1]);
3188 }
3189 else if (strcmp(ptr_arg, "string") == 0) {
3190 if (!*(args[cur_arg + 1])) {
3191 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3192 file, linenum, args[0], args[1], ptr_arg);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196 curproxy->options2 |= PR_O2_EXP_STR;
3197 curproxy->expect_str = strdup(args[cur_arg + 1]);
3198 }
3199 else if (strcmp(ptr_arg, "rstatus") == 0) {
3200 if (!*(args[cur_arg + 1])) {
3201 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3202 file, linenum, args[0], args[1], ptr_arg);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206 curproxy->options2 |= PR_O2_EXP_RSTS;
3207 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3208 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3209 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3210 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214 }
3215 else if (strcmp(ptr_arg, "rstring") == 0) {
3216 if (!*(args[cur_arg + 1])) {
3217 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3218 file, linenum, args[0], args[1], ptr_arg);
3219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
3221 }
3222 curproxy->options2 |= PR_O2_EXP_RSTR;
3223 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3224 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3225 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3226 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
3229 }
3230 }
3231 else {
3232 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3233 file, linenum, args[0], args[1], ptr_arg);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
3237 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003238 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003239 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003242 }
3243 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003244 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003245 if (curproxy == &defproxy) {
3246 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003249 }
3250
Willy Tarreaub80c2302007-11-30 20:51:32 +01003251 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003253
3254 if (strcmp(args[1], "fail") == 0) {
3255 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003256 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003257 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3258 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003261 }
3262
Willy Tarreauef6494c2010-01-28 17:12:36 +01003263 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003264 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3265 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003268 }
3269 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3270 }
3271 else {
3272 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003275 }
3276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277#ifdef TPROXY
3278 else if (!strcmp(args[0], "transparent")) {
3279 /* enable transparent proxy connections */
3280 curproxy->options |= PR_O_TRANSP;
3281 }
3282#endif
3283 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003284 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003286
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 if (*(args[1]) == 0) {
3288 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
3292 curproxy->maxconn = atol(args[1]);
3293 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003294 else if (!strcmp(args[0], "backlog")) { /* backlog */
3295 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003297
3298 if (*(args[1]) == 0) {
3299 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003302 }
3303 curproxy->backlog = atol(args[1]);
3304 }
Willy Tarreau86034312006-12-29 00:10:33 +01003305 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003308
Willy Tarreau86034312006-12-29 00:10:33 +01003309 if (*(args[1]) == 0) {
3310 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003313 }
3314 curproxy->fullconn = atol(args[1]);
3315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3317 if (*(args[1]) == 0) {
3318 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003322 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3323 if (err) {
3324 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3325 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003328 }
3329 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003332 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 if (curproxy == &defproxy) {
3334 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003338 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003340
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 if (strchr(args[1], ':') == NULL) {
3342 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003346 sk = str2sa(args[1]);
3347 if (!sk) {
3348 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
3354 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003355 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003357
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003358 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003359 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3360 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003365 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3366 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3367 err_code |= ERR_WARN;
3368
3369 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3370 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3371 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3372 }
3373 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3374 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3375 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3376 }
3377 else {
3378 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
3381 }
3382 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003383 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003385 char *rport, *raddr;
3386 short realport = 0;
3387 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003389 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003394 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396
3397 if (!*args[2]) {
3398 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003403
3404 err = invalid_char(args[1]);
3405 if (err) {
3406 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3407 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003410 }
3411
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003412 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003413 struct sockaddr_in *sk;
3414
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003415 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3417 err_code |= ERR_ALERT | ERR_ABORT;
3418 goto out;
3419 }
3420
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003421 /* the servers are linked backwards first */
3422 newsrv->next = curproxy->srv;
3423 curproxy->srv = newsrv;
3424 newsrv->proxy = curproxy;
3425 newsrv->conf.file = file;
3426 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003428 LIST_INIT(&newsrv->pendconns);
3429 do_check = 0;
3430 newsrv->state = SRV_RUNNING; /* early server setup */
3431 newsrv->last_change = now.tv_sec;
3432 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003434 /* several ways to check the port component :
3435 * - IP => port=+0, relative
3436 * - IP: => port=+0, relative
3437 * - IP:N => port=N, absolute
3438 * - IP:+N => port=+N, relative
3439 * - IP:-N => port=-N, relative
3440 */
3441 raddr = strdup(args[2]);
3442 rport = strchr(raddr, ':');
3443 if (rport) {
3444 *rport++ = 0;
3445 realport = atol(rport);
3446 if (!isdigit((unsigned char)*rport))
3447 newsrv->state |= SRV_MAPPORTS;
3448 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003450
Willy Tarreaud5191e72010-02-09 20:50:45 +01003451 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003452 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003453 if (!sk) {
3454 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
3458 newsrv->addr = *sk;
3459 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003460
3461 newsrv->check_port = curproxy->defsrv.check_port;
3462 newsrv->inter = curproxy->defsrv.inter;
3463 newsrv->fastinter = curproxy->defsrv.fastinter;
3464 newsrv->downinter = curproxy->defsrv.downinter;
3465 newsrv->rise = curproxy->defsrv.rise;
3466 newsrv->fall = curproxy->defsrv.fall;
3467 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3468 newsrv->minconn = curproxy->defsrv.minconn;
3469 newsrv->maxconn = curproxy->defsrv.maxconn;
3470 newsrv->slowstart = curproxy->defsrv.slowstart;
3471 newsrv->onerror = curproxy->defsrv.onerror;
3472 newsrv->consecutive_errors_limit
3473 = curproxy->defsrv.consecutive_errors_limit;
3474 newsrv->uweight = newsrv->iweight
3475 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003477 newsrv->curfd = -1; /* no health-check in progress */
3478 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003480 cur_arg = 3;
3481 } else {
3482 newsrv = &curproxy->defsrv;
3483 cur_arg = 1;
3484 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003485
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003487 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003488 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003489
3490 if (!*args[cur_arg + 1]) {
3491 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3492 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003495 }
3496
3497 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003498 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003499
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003500 if (newsrv->puid <= 0) {
3501 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003502 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003505 }
3506
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003507 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3508 if (node) {
3509 struct server *target = container_of(node, struct server, conf.id);
3510 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3511 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
3514 }
3515 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003516 cur_arg += 2;
3517 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003518 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 newsrv->cookie = strdup(args[cur_arg + 1]);
3520 newsrv->cklen = strlen(args[cur_arg + 1]);
3521 cur_arg += 2;
3522 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003523 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003524 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3525 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3526 cur_arg += 2;
3527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003529 if (!*args[cur_arg + 1]) {
3530 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3531 file, linenum, args[cur_arg]);
3532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
3534 }
3535
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003537 if (newsrv->rise <= 0) {
3538 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3539 file, linenum, args[cur_arg]);
3540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
3542 }
3543
Willy Tarreau96839092010-03-29 10:02:24 +02003544 if (newsrv->health)
3545 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 cur_arg += 2;
3547 }
3548 else if (!strcmp(args[cur_arg], "fall")) {
3549 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003550
3551 if (!*args[cur_arg + 1]) {
3552 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3553 file, linenum, args[cur_arg]);
3554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
3556 }
3557
3558 if (newsrv->fall <= 0) {
3559 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3560 file, linenum, args[cur_arg]);
3561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
3563 }
3564
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 cur_arg += 2;
3566 }
3567 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003568 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3569 if (err) {
3570 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3571 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003574 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003575 if (val <= 0) {
3576 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3577 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003580 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003581 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 cur_arg += 2;
3583 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003584 else if (!strcmp(args[cur_arg], "fastinter")) {
3585 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3586 if (err) {
3587 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3588 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003591 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003592 if (val <= 0) {
3593 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3594 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003597 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003598 newsrv->fastinter = val;
3599 cur_arg += 2;
3600 }
3601 else if (!strcmp(args[cur_arg], "downinter")) {
3602 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3603 if (err) {
3604 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3605 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003608 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003609 if (val <= 0) {
3610 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3611 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003614 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003615 newsrv->downinter = val;
3616 cur_arg += 2;
3617 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003618 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003619 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3620 if (!sk) {
3621 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
3625 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003626 cur_arg += 2;
3627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 else if (!strcmp(args[cur_arg], "port")) {
3629 newsrv->check_port = atol(args[cur_arg + 1]);
3630 cur_arg += 2;
3631 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003632 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 newsrv->state |= SRV_BACKUP;
3634 cur_arg ++;
3635 }
3636 else if (!strcmp(args[cur_arg], "weight")) {
3637 int w;
3638 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003639 if (w < 0 || w > 256) {
3640 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003645 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 cur_arg += 2;
3647 }
3648 else if (!strcmp(args[cur_arg], "minconn")) {
3649 newsrv->minconn = atol(args[cur_arg + 1]);
3650 cur_arg += 2;
3651 }
3652 else if (!strcmp(args[cur_arg], "maxconn")) {
3653 newsrv->maxconn = atol(args[cur_arg + 1]);
3654 cur_arg += 2;
3655 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003656 else if (!strcmp(args[cur_arg], "maxqueue")) {
3657 newsrv->maxqueue = atol(args[cur_arg + 1]);
3658 cur_arg += 2;
3659 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003660 else if (!strcmp(args[cur_arg], "slowstart")) {
3661 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003662 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003663 if (err) {
3664 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3665 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003668 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003669 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003670 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3671 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003674 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003675 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003676 cur_arg += 2;
3677 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003678 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003679
3680 if (!*args[cur_arg + 1]) {
3681 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3682 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003685 }
3686
3687 newsrv->trackit = strdup(args[cur_arg + 1]);
3688
3689 cur_arg += 2;
3690 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003691 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 global.maxsock++;
3693 do_check = 1;
3694 cur_arg += 1;
3695 }
Willy Tarreau96839092010-03-29 10:02:24 +02003696 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3697 newsrv->state |= SRV_MAINTAIN;
3698 newsrv->state &= ~SRV_RUNNING;
3699 newsrv->health = 0;
3700 cur_arg += 1;
3701 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003702 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003703 if (!strcmp(args[cur_arg + 1], "none"))
3704 newsrv->observe = HANA_OBS_NONE;
3705 else if (!strcmp(args[cur_arg + 1], "layer4"))
3706 newsrv->observe = HANA_OBS_LAYER4;
3707 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3708 if (curproxy->mode != PR_MODE_HTTP) {
3709 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3710 file, linenum, args[cur_arg + 1]);
3711 err_code |= ERR_ALERT;
3712 }
3713 newsrv->observe = HANA_OBS_LAYER7;
3714 }
3715 else {
3716 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003717 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003718 file, linenum, args[cur_arg], args[cur_arg + 1]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722
3723 cur_arg += 2;
3724 }
3725 else if (!strcmp(args[cur_arg], "on-error")) {
3726 if (!strcmp(args[cur_arg + 1], "fastinter"))
3727 newsrv->onerror = HANA_ONERR_FASTINTER;
3728 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3729 newsrv->onerror = HANA_ONERR_FAILCHK;
3730 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3731 newsrv->onerror = HANA_ONERR_SUDDTH;
3732 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3733 newsrv->onerror = HANA_ONERR_MARKDWN;
3734 else {
3735 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003736 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003737 file, linenum, args[cur_arg], args[cur_arg + 1]);
3738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
3740 }
3741
3742 cur_arg += 2;
3743 }
3744 else if (!strcmp(args[cur_arg], "error-limit")) {
3745 if (!*args[cur_arg + 1]) {
3746 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3747 file, linenum, args[cur_arg]);
3748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
3750 }
3751
3752 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3753
3754 if (newsrv->consecutive_errors_limit <= 0) {
3755 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3756 file, linenum, args[cur_arg]);
3757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
3759 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003760 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003761 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003762 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003763 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003764 struct sockaddr_in *sk;
3765
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003767#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003768 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003769 file, linenum, "source", "usesrc");
3770#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003771 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003773#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
3777 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003778 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3779 if (!sk) {
3780 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
3783 }
3784 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003785
3786 if (port_low != port_high) {
3787 int i;
3788 if (port_low <= 0 || port_low > 65535 ||
3789 port_high <= 0 || port_high > 65535 ||
3790 port_low > port_high) {
3791 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3792 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003795 }
3796 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3797 for (i = 0; i < newsrv->sport_range->size; i++)
3798 newsrv->sport_range->ports[i] = port_low + i;
3799 }
3800
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003802 while (*(args[cur_arg])) {
3803 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003804#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3805#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003806 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3807 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3808 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003811 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003812#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003813 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003814 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01003815 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003818 }
3819 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003820 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003821 newsrv->state |= SRV_TPROXY_CLI;
3822 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003823 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003824 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003825 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3826 char *name, *end;
3827
3828 name = args[cur_arg+1] + 7;
3829 while (isspace(*name))
3830 name++;
3831
3832 end = name;
3833 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3834 end++;
3835
3836 newsrv->state &= ~SRV_TPROXY_MASK;
3837 newsrv->state |= SRV_TPROXY_DYN;
3838 newsrv->bind_hdr_name = calloc(1, end - name + 1);
3839 newsrv->bind_hdr_len = end - name;
3840 memcpy(newsrv->bind_hdr_name, name, end - name);
3841 newsrv->bind_hdr_name[end-name] = '\0';
3842 newsrv->bind_hdr_occ = -1;
3843
3844 /* now look for an occurrence number */
3845 while (isspace(*end))
3846 end++;
3847 if (*end == ',') {
3848 end++;
3849 name = end;
3850 if (*end == '-')
3851 end++;
3852 while (isdigit(*end))
3853 end++;
3854 newsrv->bind_hdr_occ = strl2ic(name, end-name);
3855 }
3856
3857 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
3858 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3859 " occurrences values smaller than %d.\n",
3860 file, linenum, MAX_HDR_HISTORY);
3861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
3863 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01003864 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003865 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3866 if (!sk) {
3867 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
3870 }
3871 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003872 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003873 }
3874 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003875#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003876 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003877#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003878 cur_arg += 2;
3879 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003880#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003881 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003882 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003885#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3886 } /* "usesrc" */
3887
3888 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3889#ifdef SO_BINDTODEVICE
3890 if (!*args[cur_arg + 1]) {
3891 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3892 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003895 }
3896 if (newsrv->iface_name)
3897 free(newsrv->iface_name);
3898
3899 newsrv->iface_name = strdup(args[cur_arg + 1]);
3900 newsrv->iface_len = strlen(newsrv->iface_name);
3901 global.last_checks |= LSTCHK_NETADM;
3902#else
3903 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3904 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003907#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003908 cur_arg += 2;
3909 continue;
3910 }
3911 /* this keyword in not an option of "source" */
3912 break;
3913 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003915 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003916 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3917 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003922 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003923 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 +01003924 file, linenum, newsrv->id);
3925 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003926 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 +01003927 file, linenum);
3928
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
3932 }
3933
3934 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003935 if (newsrv->trackit) {
3936 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3937 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003940 }
3941
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003942 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3943 newsrv->check_port = newsrv->check_addr.sin_port;
3944
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3946 newsrv->check_port = realport; /* by default */
3947 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003948 /* not yet valid, because no port was set on
3949 * the server either. We'll check if we have
3950 * a known port on the first listener.
3951 */
3952 struct listener *l;
3953 l = curproxy->listen;
3954 if (l) {
3955 int port;
3956 port = (l->addr.ss_family == AF_INET6)
3957 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3958 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3959 newsrv->check_port = port;
3960 }
3961 }
3962 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3964 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003968
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003969 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02003970 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003971 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3972 err_code |= ERR_ALERT | ERR_ABORT;
3973 goto out;
3974 }
3975
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003976 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 newsrv->state |= SRV_CHECKED;
3978 }
3979
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003980 if (!defsrv) {
3981 if (newsrv->state & SRV_BACKUP)
3982 curproxy->srv_bck++;
3983 else
3984 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003985
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003986 newsrv->prev_state = newsrv->state;
3987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988 }
3989 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003990 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 int facility;
3992
3993 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3994 curproxy->logfac1 = global.logfac1;
3995 curproxy->logsrv1 = global.logsrv1;
3996 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003997 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998 curproxy->logfac2 = global.logfac2;
3999 curproxy->logsrv2 = global.logsrv2;
4000 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004001 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 }
4003 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004004 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005
4006 facility = get_log_facility(args[2]);
4007 if (facility < 0) {
4008 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4009 exit(1);
4010 }
4011
4012 level = 7; /* max syslog level = debug */
4013 if (*(args[3])) {
4014 level = get_log_level(args[3]);
4015 if (level < 0) {
4016 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4017 exit(1);
4018 }
4019 }
4020
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004021 minlvl = 0; /* limit syslog level to this level (emerg) */
4022 if (*(args[4])) {
4023 minlvl = get_log_level(args[4]);
4024 if (level < 0) {
4025 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4026 exit(1);
4027 }
4028 }
4029
Robert Tsai81ae1952007-12-05 10:47:29 +01004030 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004031 struct sockaddr_un *sk = str2sun(args[1]);
4032 if (!sk) {
4033 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4034 args[1], (int)sizeof(sk->sun_path) - 1);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
4038 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004039 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004040 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004041 struct sockaddr_in *sk = str2sa(args[1]);
4042 if (!sk) {
4043 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004048 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004049 if (!logsrv.u.in.sin_port) {
4050 logsrv.u.in.sin_port =
4051 htons(SYSLOG_PORT);
4052 }
4053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054
4055 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004056 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 curproxy->logfac1 = facility;
4058 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004059 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 }
4061 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004062 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 curproxy->logfac2 = facility;
4064 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004065 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 }
4067 else {
4068 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071 }
4072 }
4073 else {
4074 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4075 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 }
4079 }
4080 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004081 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004082 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004083
Willy Tarreau977b8e42006-12-29 14:19:17 +01004084 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004085 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004086
Willy Tarreaubaaee002006-06-26 02:48:02 +02004087 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004088 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4089 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004093
4094 /* we must first clear any optional default setting */
4095 curproxy->options &= ~PR_O_TPXY_MASK;
4096 free(curproxy->iface_name);
4097 curproxy->iface_name = NULL;
4098 curproxy->iface_len = 0;
4099
Willy Tarreaud5191e72010-02-09 20:50:45 +01004100 sk = str2sa(args[1]);
4101 if (!sk) {
4102 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004108
4109 cur_arg = 2;
4110 while (*(args[cur_arg])) {
4111 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004112#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4113#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004114 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4115 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4116 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004119 }
4120#endif
4121 if (!*args[cur_arg + 1]) {
4122 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4123 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004126 }
4127
4128 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004129 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004130 curproxy->options |= PR_O_TPXY_CLI;
4131 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004132 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004133 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004134 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4135 char *name, *end;
4136
4137 name = args[cur_arg+1] + 7;
4138 while (isspace(*name))
4139 name++;
4140
4141 end = name;
4142 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4143 end++;
4144
4145 curproxy->options &= ~PR_O_TPXY_MASK;
4146 curproxy->options |= PR_O_TPXY_DYN;
4147 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4148 curproxy->bind_hdr_len = end - name;
4149 memcpy(curproxy->bind_hdr_name, name, end - name);
4150 curproxy->bind_hdr_name[end-name] = '\0';
4151 curproxy->bind_hdr_occ = -1;
4152
4153 /* now look for an occurrence number */
4154 while (isspace(*end))
4155 end++;
4156 if (*end == ',') {
4157 end++;
4158 name = end;
4159 if (*end == '-')
4160 end++;
4161 while (isdigit(*end))
4162 end++;
4163 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4164 }
4165
4166 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4167 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4168 " occurrences values smaller than %d.\n",
4169 file, linenum, MAX_HDR_HISTORY);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004173 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004174 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4175 if (!sk) {
4176 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
4180 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004181 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004182 }
4183 global.last_checks |= LSTCHK_NETADM;
4184#if !defined(CONFIG_HAP_LINUX_TPROXY)
4185 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004186#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004187#else /* no TPROXY support */
4188 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004189 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004192#endif
4193 cur_arg += 2;
4194 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004195 }
4196
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004197 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4198#ifdef SO_BINDTODEVICE
4199 if (!*args[cur_arg + 1]) {
4200 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4201 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004204 }
4205 if (curproxy->iface_name)
4206 free(curproxy->iface_name);
4207
4208 curproxy->iface_name = strdup(args[cur_arg + 1]);
4209 curproxy->iface_len = strlen(curproxy->iface_name);
4210 global.last_checks |= LSTCHK_NETADM;
4211#else
4212 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4213 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004216#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004217 cur_arg += 2;
4218 continue;
4219 }
4220 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4221 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004226 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4227 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4228 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004233 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4235 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004238 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004239
4240 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4241 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004242 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004243 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 }
4246 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004247 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4248 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004249 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004250 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 }
4253 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004254 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4255 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004256 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004257 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259 }
4260 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004261 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4262 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004263 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004264 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004266 }
4267 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004268 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4269 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004270 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004271 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004274 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4276 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004277 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004279 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004280 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004281 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4283 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004284 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004286 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004287 }
4288 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4290 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004291 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004293 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004296 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004302
4303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4304 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004305 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 }
4309 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004310 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4311 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004312 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004313 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 }
4316 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004317 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4318 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004319 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004320 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 }
4323 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004324 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4325 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004326 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004327 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 }
4330 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004331 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4332 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004333 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004334 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004337 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004338 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4339 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004340 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004341 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004342 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004343 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004345 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004346
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347 if (curproxy == &defproxy) {
4348 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004352 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004353 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004354
Willy Tarreaubaaee002006-06-26 02:48:02 +02004355 if (*(args[1]) == 0) {
4356 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004360
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004361 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4362 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4363 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4364 file, linenum, args[0]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4369 }
4370 else if (*args[2]) {
4371 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4372 file, linenum, args[0], args[2]);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004377 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004378 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004379 wl->s = strdup(args[1]);
4380 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004381 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004382 }
4383 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004384 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004390
Willy Tarreauade5ec42010-01-28 19:33:49 +01004391 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4392 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004393 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004394 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 }
4397 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004398 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4399 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004400 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004401 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 }
4404 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004405 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4406 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004407 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004408 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004410 }
4411 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004412 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004413 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4414 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 }
4418
Willy Tarreauade5ec42010-01-28 19:33:49 +01004419 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4420 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004421 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004422 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004424 }
4425 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004426 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4427 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004428 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004429 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
4432 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004433 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4434 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004435 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004436 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 }
4439 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004440 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004441
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 if (curproxy == &defproxy) {
4443 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004447 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004448 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 if (*(args[1]) == 0) {
4451 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 }
4455
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004456 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4457 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4458 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4459 file, linenum, args[0]);
4460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
4462 }
4463 err_code |= warnif_cond_requires_req(cond, file, linenum);
4464 }
4465 else if (*args[2]) {
4466 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4467 file, linenum, args[0], args[2]);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
4470 }
4471
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004472 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004473 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004474 wl->s = strdup(args[1]);
4475 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 }
4477 else if (!strcmp(args[0], "errorloc") ||
4478 !strcmp(args[0], "errorloc302") ||
4479 !strcmp(args[0], "errorloc303")) { /* error location */
4480 int errnum, errlen;
4481 char *err;
4482
Willy Tarreau977b8e42006-12-29 14:19:17 +01004483 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004484 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004485
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004487 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 }
4491
4492 errnum = atol(args[1]);
4493 if (!strcmp(args[0], "errorloc303")) {
4494 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4495 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4496 } else {
4497 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4498 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4499 }
4500
Willy Tarreau0f772532006-12-23 20:51:41 +01004501 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4502 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004503 chunk_destroy(&curproxy->errmsg[rc]);
4504 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004505 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004508
4509 if (rc >= HTTP_ERR_SIZE) {
4510 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4511 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 free(err);
4513 }
4514 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004515 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4516 int errnum, errlen, fd;
4517 char *err;
4518 struct stat stat;
4519
4520 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004521 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004522
4523 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004524 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004527 }
4528
4529 fd = open(args[2], O_RDONLY);
4530 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4531 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4532 file, linenum, args[2], args[1]);
4533 if (fd >= 0)
4534 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004537 }
4538
Willy Tarreau27a674e2009-08-17 07:23:33 +02004539 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004540 errlen = stat.st_size;
4541 } else {
4542 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004543 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004545 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004546 }
4547
4548 err = malloc(errlen); /* malloc() must succeed during parsing */
4549 errnum = read(fd, err, errlen);
4550 if (errnum != errlen) {
4551 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4552 file, linenum, args[2], args[1]);
4553 close(fd);
4554 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004557 }
4558 close(fd);
4559
4560 errnum = atol(args[1]);
4561 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4562 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004563 chunk_destroy(&curproxy->errmsg[rc]);
4564 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004565 break;
4566 }
4567 }
4568
4569 if (rc >= HTTP_ERR_SIZE) {
4570 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4571 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004573 free(err);
4574 }
4575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004577 struct cfg_kw_list *kwl;
4578 int index;
4579
4580 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4581 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4582 if (kwl->kw[index].section != CFG_LISTEN)
4583 continue;
4584 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4585 /* prepare error message just in case */
4586 snprintf(trash, sizeof(trash),
4587 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004588 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4589 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004590 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004593 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004594 else if (rc > 0) {
4595 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_WARN;
4597 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004598 }
Willy Tarreau93893792009-07-23 13:19:11 +02004599 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004600 }
4601 }
4602 }
4603
Willy Tarreau6daf3432008-01-22 16:44:08 +01004604 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 }
Willy Tarreau93893792009-07-23 13:19:11 +02004608 out:
4609 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610}
4611
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004612int
4613cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4614{
4615
4616 int err_code = 0;
4617 const char *err;
4618
4619 if (!strcmp(args[0], "userlist")) { /* new userlist */
4620 struct userlist *newul;
4621
4622 if (!*args[1]) {
4623 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4624 file, linenum, args[0]);
4625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
4627 }
4628
4629 err = invalid_char(args[1]);
4630 if (err) {
4631 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4632 file, linenum, *err, args[0], args[1]);
4633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
4636
4637 for (newul = userlist; newul; newul = newul->next)
4638 if (!strcmp(newul->name, args[1])) {
4639 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4640 file, linenum, args[1]);
4641 err_code |= ERR_WARN;
4642 goto out;
4643 }
4644
4645 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4646 if (!newul) {
4647 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4648 err_code |= ERR_ALERT | ERR_ABORT;
4649 goto out;
4650 }
4651
4652 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4653 newul->name = strdup(args[1]);
4654
4655 if (!newul->groupusers | !newul->name) {
4656 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4657 err_code |= ERR_ALERT | ERR_ABORT;
4658 goto out;
4659 }
4660
4661 newul->next = userlist;
4662 userlist = newul;
4663
4664 } else if (!strcmp(args[0], "group")) { /* new group */
4665 int cur_arg, i;
4666 const char *err;
4667
4668 if (!*args[1]) {
4669 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4670 file, linenum, args[0]);
4671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
4673 }
4674
4675 err = invalid_char(args[1]);
4676 if (err) {
4677 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4678 file, linenum, *err, args[0], args[1]);
4679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
4681 }
4682
4683 for(i = 0; i < userlist->grpcnt; i++)
4684 if (!strcmp(userlist->groups[i], args[1])) {
4685 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4686 file, linenum, args[1], userlist->name);
4687 err_code |= ERR_ALERT;
4688 goto out;
4689 }
4690
4691 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4692 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4693 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696 }
4697
4698 cur_arg = 2;
4699
4700 while (*args[cur_arg]) {
4701 if (!strcmp(args[cur_arg], "users")) {
4702 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4703 cur_arg += 2;
4704 continue;
4705 } else {
4706 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4707 file, linenum, args[0]);
4708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
4711 }
4712
4713 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4714 } else if (!strcmp(args[0], "user")) { /* new user */
4715 struct auth_users *newuser;
4716 int cur_arg;
4717
4718 if (!*args[1]) {
4719 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4720 file, linenum, args[0]);
4721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
4723 }
4724
4725 for (newuser = userlist->users; newuser; newuser = newuser->next)
4726 if (!strcmp(newuser->user, args[1])) {
4727 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4728 file, linenum, args[1], userlist->name);
4729 err_code |= ERR_ALERT;
4730 goto out;
4731 }
4732
4733 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4734 if (!newuser) {
4735 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4736 err_code |= ERR_ALERT | ERR_ABORT;
4737 goto out;
4738 }
4739
4740 newuser->user = strdup(args[1]);
4741
4742 newuser->next = userlist->users;
4743 userlist->users = newuser;
4744
4745 cur_arg = 2;
4746
4747 while (*args[cur_arg]) {
4748 if (!strcmp(args[cur_arg], "password")) {
4749#ifndef CONFIG_HAP_CRYPT
4750 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4751 file, linenum);
4752 err_code |= ERR_ALERT;
4753#endif
4754 newuser->pass = strdup(args[cur_arg + 1]);
4755 cur_arg += 2;
4756 continue;
4757 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4758 newuser->pass = strdup(args[cur_arg + 1]);
4759 newuser->flags |= AU_O_INSECURE;
4760 cur_arg += 2;
4761 continue;
4762 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004763 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004764 cur_arg += 2;
4765 continue;
4766 } else {
4767 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4768 file, linenum, args[0]);
4769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
4771 }
4772 }
4773 } else {
4774 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 }
4777
4778out:
4779 return err_code;
4780}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781
4782/*
4783 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004784 * Returns the error code, 0 if OK, or any combination of :
4785 * - ERR_ABORT: must abort ASAP
4786 * - ERR_FATAL: we can continue parsing but not start the service
4787 * - ERR_WARN: a warning has been emitted
4788 * - ERR_ALERT: an alert has been emitted
4789 * Only the two first ones can stop processing, the two others are just
4790 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004792int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004794 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 FILE *f;
4796 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004797 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004798 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 if ((f=fopen(file,"r")) == NULL)
4801 return -1;
4802
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004803 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004804 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004805 char *end;
4806 char *args[MAX_LINE_ARGS + 1];
4807 char *line = thisline;
4808
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 linenum++;
4810
4811 end = line + strlen(line);
4812
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004813 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4814 /* Check if we reached the limit and the last char is not \n.
4815 * Watch out for the last line without the terminating '\n'!
4816 */
4817 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004818 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004820 }
4821
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004823 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 line++;
4825
4826 arg = 0;
4827 args[arg] = line;
4828
4829 while (*line && arg < MAX_LINE_ARGS) {
4830 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4831 * C equivalent value. Other combinations left unchanged (eg: \1).
4832 */
4833 if (*line == '\\') {
4834 int skip = 0;
4835 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4836 *line = line[1];
4837 skip = 1;
4838 }
4839 else if (line[1] == 'r') {
4840 *line = '\r';
4841 skip = 1;
4842 }
4843 else if (line[1] == 'n') {
4844 *line = '\n';
4845 skip = 1;
4846 }
4847 else if (line[1] == 't') {
4848 *line = '\t';
4849 skip = 1;
4850 }
4851 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004852 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 unsigned char hex1, hex2;
4854 hex1 = toupper(line[2]) - '0';
4855 hex2 = toupper(line[3]) - '0';
4856 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4857 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4858 *line = (hex1<<4) + hex2;
4859 skip = 3;
4860 }
4861 else {
4862 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004863 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
4865 }
4866 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004867 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 end -= skip;
4869 }
4870 line++;
4871 }
4872 else if (*line == '#' || *line == '\n' || *line == '\r') {
4873 /* end of string, end of loop */
4874 *line = 0;
4875 break;
4876 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004877 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004879 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004880 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 line++;
4882 args[++arg] = line;
4883 }
4884 else {
4885 line++;
4886 }
4887 }
4888
4889 /* empty line */
4890 if (!**args)
4891 continue;
4892
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004893 if (*line) {
4894 /* we had to stop due to too many args.
4895 * Let's terminate the string, print the offending part then cut the
4896 * last arg.
4897 */
4898 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4899 line++;
4900 *line = '\0';
4901
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004902 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004903 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004904 err_code |= ERR_ALERT | ERR_FATAL;
4905 args[arg] = line;
4906 }
4907
Willy Tarreau540abe42007-05-02 20:50:16 +02004908 /* zero out remaining args and ensure that at least one entry
4909 * is zeroed out.
4910 */
4911 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 args[arg] = line;
4913 }
4914
Willy Tarreau3842f002009-06-14 11:39:52 +02004915 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004916 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004917 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004918 for (arg=0; *args[arg+1]; arg++)
4919 args[arg] = args[arg+1]; // shift args after inversion
4920 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004921 else if (!strcmp(args[0], "default")) {
4922 kwm = KWM_DEF;
4923 for (arg=0; *args[arg+1]; arg++)
4924 args[arg] = args[arg+1]; // shift args after inversion
4925 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004926
Willy Tarreau3842f002009-06-14 11:39:52 +02004927 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4928 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004930 }
4931
Willy Tarreau977b8e42006-12-29 14:19:17 +01004932 if (!strcmp(args[0], "listen") ||
4933 !strcmp(args[0], "frontend") ||
4934 !strcmp(args[0], "backend") ||
4935 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004936 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004938 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004939 cursection = strdup(args[0]);
4940 }
4941 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004943 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004944 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004945 } else if (!strcmp(args[0], "userlist")) {
4946 confsect = CFG_USERLIST;
4947 free(cursection);
4948 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 /* else it's a section keyword */
4951
4952 switch (confsect) {
4953 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004954 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 break;
4956 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004957 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004959 case CFG_USERLIST:
4960 err_code |= cfg_parse_users(file, linenum, args, kwm);
4961 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004963 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004966
4967 if (err_code & ERR_ABORT)
4968 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004970 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004971 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004973 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004974}
4975
Willy Tarreaubb925012009-07-23 13:36:36 +02004976/*
4977 * Returns the error code, 0 if OK, or any combination of :
4978 * - ERR_ABORT: must abort ASAP
4979 * - ERR_FATAL: we can continue parsing but not start the service
4980 * - ERR_WARN: a warning has been emitted
4981 * - ERR_ALERT: an alert has been emitted
4982 * Only the two first ones can stop processing, the two others are just
4983 * indicators.
4984 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004985int check_config_validity()
4986{
4987 int cfgerr = 0;
4988 struct proxy *curproxy = NULL;
4989 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004990 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004991 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004992 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993
4994 /*
4995 * Now, check for the integrity of all that we have collected.
4996 */
4997
4998 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004999 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005001 /* first, we will invert the proxy list order */
5002 curproxy = NULL;
5003 while (proxy) {
5004 struct proxy *next;
5005
5006 next = proxy->next;
5007 proxy->next = curproxy;
5008 curproxy = proxy;
5009 if (!next)
5010 break;
5011 proxy = next;
5012 }
5013
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005015 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
5019
5020 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005021 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005022 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005023 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005024 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005025 unsigned int next_id;
5026
5027 if (!curproxy->uuid) {
5028 /* proxy ID not set, use automatic numbering with first
5029 * spare entry starting with next_pxid.
5030 */
5031 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5032 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5033 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005034 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005035 next_pxid++;
5036
Willy Tarreau55ea7572007-06-17 19:56:27 +02005037
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005039 /* ensure we don't keep listeners uselessly bound */
5040 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 curproxy = curproxy->next;
5042 continue;
5043 }
5044
Willy Tarreauff01a212009-03-15 13:46:16 +01005045 switch (curproxy->mode) {
5046 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005047 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005048 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005049 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5050 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005051 cfgerr++;
5052 }
5053
5054 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005055 Warning("config : servers will be ignored for %s '%s'.\n",
5056 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005057 break;
5058
5059 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005060 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005061 break;
5062
5063 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005064 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005065 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005066 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5067 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005068 cfgerr++;
5069 }
5070 break;
5071 }
5072
5073 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005074 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5075 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 cfgerr++;
5077 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005078
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005079 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005080 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005081 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005082 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5083 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005084 cfgerr++;
5085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005087 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005088 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5089 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005090 cfgerr++;
5091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005093 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005094 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5095 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005096 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005097 }
5098 }
5099 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5100 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5101 /* If no LB algo is set in a backend, and we're not in
5102 * transparent mode, dispatch mode nor proxy mode, we
5103 * want to use balance roundrobin by default.
5104 */
5105 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5106 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 }
5108 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005109
Willy Tarreau82936582007-11-30 15:20:09 +01005110 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5111 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005112 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5113 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005114 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005115 }
5116
Willy Tarreauef781042010-01-27 11:53:01 +01005117 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5118 curproxy->options &= ~PR_O2_CHK_SNDST;
5119 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5120 "send-state", proxy_type_str(curproxy), curproxy->id);
5121 err_code |= ERR_WARN;
5122 }
5123
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005124 /* if a default backend was specified, let's find it */
5125 if (curproxy->defbe.name) {
5126 struct proxy *target;
5127
Alex Williams96532db2009-11-01 21:27:13 -05005128 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005129 if (!target) {
5130 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5131 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005132 cfgerr++;
5133 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005134 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5135 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005136 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005137 } else {
5138 free(curproxy->defbe.name);
5139 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005140 /* we force the backend to be present on at least all of
5141 * the frontend's processes.
5142 */
5143 target->bind_proc = curproxy->bind_proc ?
5144 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
5146 }
5147
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005148 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005149 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5150 /* map jump target for ACT_SETBE in req_rep chain */
5151 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005152 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005153 struct proxy *target;
5154
Willy Tarreaua496b602006-12-17 23:15:24 +01005155 if (exp->action != ACT_SETBE)
5156 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005157
Alex Williams96532db2009-11-01 21:27:13 -05005158 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005159 if (!target) {
5160 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5161 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005162 cfgerr++;
5163 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005164 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5165 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005166 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005167 } else {
5168 free((void *)exp->replace);
5169 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005170 /* we force the backend to be present on at least all of
5171 * the frontend's processes.
5172 */
5173 target->bind_proc = curproxy->bind_proc ?
5174 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005175 }
5176 }
5177 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005178
5179 /* find the target proxy for 'use_backend' rules */
5180 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005181 struct proxy *target;
5182
Alex Williams96532db2009-11-01 21:27:13 -05005183 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005184
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005185 if (!target) {
5186 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5187 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005188 cfgerr++;
5189 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005190 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5191 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005192 cfgerr++;
5193 } else {
5194 free((void *)rule->be.name);
5195 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005196 /* we force the backend to be present on at least all of
5197 * the frontend's processes.
5198 */
5199 target->bind_proc = curproxy->bind_proc ?
5200 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005201 }
5202 }
5203
Emeric Brunb982a3d2010-01-04 15:45:53 +01005204 /* find the target table for 'stick' rules */
5205 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5206 struct proxy *target;
5207
Emeric Brun1d33b292010-01-04 15:47:17 +01005208 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5209 if (mrule->flags & STK_IS_STORE)
5210 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5211
Emeric Brunb982a3d2010-01-04 15:45:53 +01005212 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005213 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005214 else
5215 target = curproxy;
5216
5217 if (!target) {
5218 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5219 curproxy->id, mrule->table.name);
5220 cfgerr++;
5221 }
5222 else if (target->table.size == 0) {
5223 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5224 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5225 cfgerr++;
5226 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005227 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005228 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5229 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5230 cfgerr++;
5231 }
5232 else {
5233 free((void *)mrule->table.name);
5234 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005235 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005236 }
5237 }
5238
5239 /* find the target table for 'store response' rules */
5240 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5241 struct proxy *target;
5242
Emeric Brun1d33b292010-01-04 15:47:17 +01005243 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5244
Emeric Brunb982a3d2010-01-04 15:45:53 +01005245 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005246 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005247 else
5248 target = curproxy;
5249
5250 if (!target) {
5251 Alert("Proxy '%s': unable to find store table '%s'.\n",
5252 curproxy->id, mrule->table.name);
5253 cfgerr++;
5254 }
5255 else if (target->table.size == 0) {
5256 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5257 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5258 cfgerr++;
5259 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005260 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005261 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5262 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5263 cfgerr++;
5264 }
5265 else {
5266 free((void *)mrule->table.name);
5267 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005268 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005269 }
5270 }
5271
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005272 /* find the target table for 'tcp-request' layer 4 rules */
5273 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5274 struct proxy *target;
5275
Willy Tarreau56123282010-08-06 19:06:56 +02005276 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005277 continue;
5278
5279 if (trule->act_prm.trk_ctr.table.n)
5280 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5281 else
5282 target = curproxy;
5283
5284 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005285 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5286 curproxy->id, trule->act_prm.trk_ctr.table.n,
5287 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005288 cfgerr++;
5289 }
5290 else if (target->table.size == 0) {
5291 Alert("Proxy '%s': table '%s' used but not configured.\n",
5292 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5293 cfgerr++;
5294 }
5295 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005296 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 +02005297 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5298 cfgerr++;
5299 }
5300 else {
5301 free(trule->act_prm.trk_ctr.table.n);
5302 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005303 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005304 * to pass a list of counters to track and allocate them right here using
5305 * stktable_alloc_data_type().
5306 */
5307 }
5308 }
5309
Willy Tarreaud1f96522010-08-03 19:34:32 +02005310 /* find the target table for 'tcp-request' layer 6 rules */
5311 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5312 struct proxy *target;
5313
Willy Tarreau56123282010-08-06 19:06:56 +02005314 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005315 continue;
5316
5317 if (trule->act_prm.trk_ctr.table.n)
5318 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5319 else
5320 target = curproxy;
5321
5322 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005323 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5324 curproxy->id, trule->act_prm.trk_ctr.table.n,
5325 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005326 cfgerr++;
5327 }
5328 else if (target->table.size == 0) {
5329 Alert("Proxy '%s': table '%s' used but not configured.\n",
5330 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5331 cfgerr++;
5332 }
5333 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005334 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 +02005335 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5336 cfgerr++;
5337 }
5338 else {
5339 free(trule->act_prm.trk_ctr.table.n);
5340 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005341 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005342 * to pass a list of counters to track and allocate them right here using
5343 * stktable_alloc_data_type().
5344 */
5345 }
5346 }
5347
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005348 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5349 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005350 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5351 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5352 "proxy", curproxy->id);
5353 cfgerr++;
5354 goto out_uri_auth_compat;
5355 }
5356
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005357 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005358 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005359 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005360 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005361
Willy Tarreau95fa4692010-02-01 13:05:50 +01005362 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5363 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005364
5365 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005366 uri_auth_compat_req[i++] = "realm";
5367 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5368 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005369
Willy Tarreau95fa4692010-02-01 13:05:50 +01005370 uri_auth_compat_req[i++] = "unless";
5371 uri_auth_compat_req[i++] = "{";
5372 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5373 uri_auth_compat_req[i++] = "}";
5374 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005375
Willy Tarreau95fa4692010-02-01 13:05:50 +01005376 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5377 if (!req_acl) {
5378 cfgerr++;
5379 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005380 }
5381
Willy Tarreau95fa4692010-02-01 13:05:50 +01005382 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5383
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005384 if (curproxy->uri_auth->auth_realm) {
5385 free(curproxy->uri_auth->auth_realm);
5386 curproxy->uri_auth->auth_realm = NULL;
5387 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005388
5389 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005390 }
5391out_uri_auth_compat:
5392
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005393 cfgerr += acl_find_targets(curproxy);
5394
Willy Tarreau2738a142006-07-08 17:28:09 +02005395 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005396 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005397 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005398 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005399 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005400 " | While not properly invalid, you will certainly encounter various problems\n"
5401 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005402 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005403 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005404 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005405 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005406
Willy Tarreau1fa31262007-12-03 00:36:16 +01005407 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5408 * We must still support older configurations, so let's find out whether those
5409 * parameters have been set or must be copied from contimeouts.
5410 */
5411 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005412 if (!curproxy->timeout.tarpit ||
5413 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005414 /* tarpit timeout not set. We search in the following order:
5415 * default.tarpit, curr.connect, default.connect.
5416 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005417 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005418 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005419 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005420 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005421 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005422 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005423 }
5424 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005425 (!curproxy->timeout.queue ||
5426 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005427 /* queue timeout not set. We search in the following order:
5428 * default.queue, curr.connect, default.connect.
5429 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005430 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005431 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005432 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005433 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005434 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005435 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005436 }
5437 }
5438
Willy Tarreau07a54902010-03-29 18:33:29 +02005439 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005440 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5441 curproxy->check_req = (char *)malloc(curproxy->check_len);
5442 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005443 }
5444
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005445 /* The small pools required for the capture lists */
5446 if (curproxy->nb_req_cap)
5447 curproxy->req_cap_pool = create_pool("ptrcap",
5448 curproxy->nb_req_cap * sizeof(char *),
5449 MEM_F_SHARED);
5450 if (curproxy->nb_rsp_cap)
5451 curproxy->rsp_cap_pool = create_pool("ptrcap",
5452 curproxy->nb_rsp_cap * sizeof(char *),
5453 MEM_F_SHARED);
5454
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005455 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5456 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5457 MEM_F_SHARED);
5458
Willy Tarreau86034312006-12-29 00:10:33 +01005459 /* for backwards compatibility with "listen" instances, if
5460 * fullconn is not set but maxconn is set, then maxconn
5461 * is used.
5462 */
5463 if (!curproxy->fullconn)
5464 curproxy->fullconn = curproxy->maxconn;
5465
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 /* first, we will invert the servers list order */
5467 newsrv = NULL;
5468 while (curproxy->srv) {
5469 struct server *next;
5470
5471 next = curproxy->srv->next;
5472 curproxy->srv->next = newsrv;
5473 newsrv = curproxy->srv;
5474 if (!next)
5475 break;
5476 curproxy->srv = next;
5477 }
5478
Willy Tarreaudd701652010-05-25 23:03:02 +02005479 /* assign automatic UIDs to servers which don't have one yet */
5480 next_id = 1;
5481 newsrv = curproxy->srv;
5482 while (newsrv != NULL) {
5483 if (!newsrv->puid) {
5484 /* server ID not set, use automatic numbering with first
5485 * spare entry starting with next_svid.
5486 */
5487 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5488 newsrv->conf.id.key = newsrv->puid = next_id;
5489 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5490 }
5491 next_id++;
5492 newsrv = newsrv->next;
5493 }
5494
Willy Tarreau20697042007-11-15 23:26:18 +01005495 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005496 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005498 /* We have to initialize the server lookup mechanism depending
5499 * on what LB algorithm was choosen.
5500 */
5501
5502 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5503 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5504 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005505 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5506 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5507 init_server_map(curproxy);
5508 } else {
5509 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5510 fwrr_init_server_groups(curproxy);
5511 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005512 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005513
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005514 case BE_LB_KIND_LC:
5515 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005516 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005517 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005518
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005519 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005520 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5521 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5522 chash_init_server_tree(curproxy);
5523 } else {
5524 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5525 init_server_map(curproxy);
5526 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005527 break;
5528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529
5530 if (curproxy->options & PR_O_LOGASAP)
5531 curproxy->to_log &= ~LW_BYTES;
5532
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005533 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5534 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5535 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5536 proxy_type_str(curproxy), curproxy->id);
5537 err_code |= ERR_WARN;
5538 }
5539
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005540 if (curproxy->mode != PR_MODE_HTTP) {
5541 int optnum;
5542
5543 if (curproxy->options & PR_O_COOK_ANY) {
5544 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5545 proxy_type_str(curproxy), curproxy->id);
5546 err_code |= ERR_WARN;
5547 }
5548
5549 if (curproxy->uri_auth) {
5550 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5551 proxy_type_str(curproxy), curproxy->id);
5552 err_code |= ERR_WARN;
5553 curproxy->uri_auth = NULL;
5554 }
5555
5556 if (curproxy->options & PR_O_FWDFOR) {
5557 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5558 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5559 err_code |= ERR_WARN;
5560 curproxy->options &= ~PR_O_FWDFOR;
5561 }
5562
5563 if (curproxy->options & PR_O_ORGTO) {
5564 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5565 "originalto", proxy_type_str(curproxy), curproxy->id);
5566 err_code |= ERR_WARN;
5567 curproxy->options &= ~PR_O_ORGTO;
5568 }
5569
5570 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5571 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5572 (curproxy->cap & cfg_opts[optnum].cap) &&
5573 (curproxy->options & cfg_opts[optnum].val)) {
5574 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5575 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5576 err_code |= ERR_WARN;
5577 curproxy->options &= ~cfg_opts[optnum].val;
5578 }
5579 }
5580
5581 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5582 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5583 (curproxy->cap & cfg_opts2[optnum].cap) &&
5584 (curproxy->options2 & cfg_opts2[optnum].val)) {
5585 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5586 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5587 err_code |= ERR_WARN;
5588 curproxy->options2 &= ~cfg_opts2[optnum].val;
5589 }
5590 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005591
Willy Tarreauefa5f512010-03-30 20:13:29 +02005592#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005593 if (curproxy->bind_hdr_occ) {
5594 curproxy->bind_hdr_occ = 0;
5595 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5596 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5597 err_code |= ERR_WARN;
5598 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005599#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005600 }
5601
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005603 * ensure that we're not cross-dressing a TCP server into HTTP.
5604 */
5605 newsrv = curproxy->srv;
5606 while (newsrv != NULL) {
5607 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005608 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5609 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005610 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005611 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005612
Willy Tarreauefa5f512010-03-30 20:13:29 +02005613#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005614 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5615 newsrv->bind_hdr_occ = 0;
5616 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5617 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5618 err_code |= ERR_WARN;
5619 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005620#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005621 newsrv = newsrv->next;
5622 }
5623
5624 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 * If this server supports a maxconn parameter, it needs a dedicated
5626 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005627 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 */
5629 newsrv = curproxy->srv;
5630 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005631 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 /* Only 'minconn' was specified, or it was higher than or equal
5633 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5634 * this will avoid further useless expensive computations.
5635 */
5636 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005637 } else if (newsrv->maxconn && !newsrv->minconn) {
5638 /* minconn was not specified, so we set it to maxconn */
5639 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005640 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005641 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5642 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005643 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644 }
5645
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005646 if (newsrv->trackit) {
5647 struct proxy *px;
5648 struct server *srv;
5649 char *pname, *sname;
5650
5651 pname = newsrv->trackit;
5652 sname = strrchr(pname, '/');
5653
5654 if (sname)
5655 *sname++ = '\0';
5656 else {
5657 sname = pname;
5658 pname = NULL;
5659 }
5660
5661 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005662 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005663 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005664 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5665 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005666 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005667 cfgerr++;
5668 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005669 }
5670 } else
5671 px = curproxy;
5672
5673 srv = findserver(px, sname);
5674 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005675 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5676 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005677 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005678 cfgerr++;
5679 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005680 }
5681
5682 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005683 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005684 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005685 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005686 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005687 cfgerr++;
5688 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005689 }
5690
5691 if (curproxy != px &&
5692 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005693 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005694 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005695 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005696 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005697 cfgerr++;
5698 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005699 }
5700
5701 newsrv->tracked = srv;
5702 newsrv->tracknext = srv->tracknext;
5703 srv->tracknext = newsrv;
5704
5705 free(newsrv->trackit);
5706 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005707 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708 newsrv = newsrv->next;
5709 }
5710
Willy Tarreauc1a21672009-08-16 22:37:44 +02005711 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005712 curproxy->accept = frontend_accept;
5713
Willy Tarreauc1a21672009-08-16 22:37:44 +02005714 if (curproxy->tcp_req.inspect_delay ||
5715 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02005716 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005717
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005718 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005719 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005720 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005721 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005722
5723 /* both TCP and HTTP must check switching rules */
5724 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5725 }
5726
5727 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02005728 if (curproxy->tcp_req.inspect_delay ||
5729 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5730 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
5731
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005732 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005733 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005734 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005735 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005736
5737 /* If the backend does requires RDP cookie persistence, we have to
5738 * enable the corresponding analyser.
5739 */
5740 if (curproxy->options2 & PR_O2_RDPC_PRST)
5741 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5742 }
5743
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005744 listener = NULL;
5745 while (curproxy->listen) {
5746 struct listener *next;
5747
5748 next = curproxy->listen->next;
5749 curproxy->listen->next = listener;
5750 listener = curproxy->listen;
5751
5752 if (!next)
5753 break;
5754
5755 curproxy->listen = next;
5756 }
5757
Willy Tarreaue6b98942007-10-29 01:09:36 +01005758 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005759 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005760 listener = curproxy->listen;
5761 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005762 if (!listener->luid) {
5763 /* listener ID not set, use automatic numbering with first
5764 * spare entry starting with next_luid.
5765 */
5766 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5767 listener->conf.id.key = listener->luid = next_id;
5768 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005769 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005770 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005771
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005772 /* enable separate counters */
5773 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5774 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5775 if (!listener->name) {
5776 sprintf(trash, "sock-%d", listener->luid);
5777 listener->name = strdup(trash);
5778 }
5779 }
5780
Willy Tarreaue6b98942007-10-29 01:09:36 +01005781 if (curproxy->options & PR_O_TCP_NOLING)
5782 listener->options |= LI_O_NOLINGER;
5783 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005784 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005785 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005786 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02005787 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005788 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005789 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005790
Willy Tarreau8a956912010-10-15 14:27:08 +02005791 if (listener->options & LI_O_ACC_PROXY)
5792 listener->analysers |= AN_REQ_DECODE_PROXY;
5793
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02005794 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
5795 listener->options |= LI_O_TCP_RULES;
5796
Willy Tarreaude3041d2010-05-31 10:56:17 +02005797 if (curproxy->mon_mask.s_addr)
5798 listener->options |= LI_O_CHK_MONNET;
5799
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005800 /* smart accept mode is automatic in HTTP mode */
5801 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5802 (curproxy->mode == PR_MODE_HTTP &&
5803 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5804 listener->options |= LI_O_NOQUICKACK;
5805
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005806 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005807 listener = listener->next;
5808 }
5809
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 curproxy = curproxy->next;
5811 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005812
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005813 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5814 struct auth_users *curuser;
5815 int g;
5816
5817 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5818 unsigned int group_mask = 0;
5819 char *group = NULL;
5820
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005821 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005822 continue;
5823
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005824 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005825
5826 for (g = 0; g < curuserlist->grpcnt; g++)
5827 if (!strcmp(curuserlist->groups[g], group))
5828 break;
5829
5830 if (g == curuserlist->grpcnt) {
5831 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5832 curuserlist->name, group, curuser->user);
5833 err_code |= ERR_ALERT | ERR_FATAL;
5834 goto out;
5835 }
5836
5837 group_mask |= (1 << g);
5838 }
5839
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005840 free(curuser->u.groups);
5841 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005842 }
5843
5844 for (g = 0; g < curuserlist->grpcnt; g++) {
5845 char *user = NULL;
5846
5847 if (!curuserlist->groupusers[g])
5848 continue;
5849
5850 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5851 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5852 if (!strcmp(curuser->user, user))
5853 break;
5854
5855 if (!curuser) {
5856 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5857 curuserlist->name, user, curuserlist->groups[g]);
5858 err_code |= ERR_ALERT | ERR_FATAL;
5859 goto out;
5860 }
5861
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005862 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005863 }
5864
5865 free(curuserlist->groupusers[g]);
5866 }
5867
5868 free(curuserlist->groupusers);
5869
5870#ifdef DEBUG_AUTH
5871 for (g = 0; g < curuserlist->grpcnt; g++) {
5872 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5873
5874 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5875 if (curuser->group_mask & (1 << g))
5876 fprintf(stderr, " %s", curuser->user);
5877 }
5878
5879 fprintf(stderr, "\n");
5880 }
5881#endif
5882
5883 }
5884
Willy Tarreau056f5682010-06-06 15:51:11 +02005885 /* initialize stick-tables on backend capable proxies. This must not
5886 * be done earlier because the data size may be discovered while parsing
5887 * other proxies.
5888 */
5889 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005890 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02005891
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005892 /*
5893 * Recount currently required checks.
5894 */
5895
5896 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5897 int optnum;
5898
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005899 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5900 if (curproxy->options & cfg_opts[optnum].val)
5901 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005902
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005903 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5904 if (curproxy->options2 & cfg_opts2[optnum].val)
5905 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005906 }
5907
Willy Tarreaubb925012009-07-23 13:36:36 +02005908 if (cfgerr > 0)
5909 err_code |= ERR_ALERT | ERR_FATAL;
5910 out:
5911 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912}
5913
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005914/*
5915 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5916 * parsing sessions.
5917 */
5918void cfg_register_keywords(struct cfg_kw_list *kwl)
5919{
5920 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5921}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005923/*
5924 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5925 */
5926void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5927{
5928 LIST_DEL(&kwl->list);
5929 LIST_INIT(&kwl->list);
5930}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931
5932/*
5933 * Local variables:
5934 * c-indent-level: 8
5935 * c-basic-offset: 8
5936 * End:
5937 */