blob: 18cfda39dbb72db5bbe7b0d3279b71accfd55149 [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>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010047#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
189 char *c, *next, *range, *dupstr;
190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
210 Alert("Socket path '%s' too long (max %d)\n", str, max_path_len);
211 goto fail;
212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200215 ss.ss_family = AF_UNIX;
216 if (global.unix_bind.prefix) {
217 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
218 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 }
Emeric Bruned760922010-10-22 17:59:25 +0200220 else {
221 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
222 }
223 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 }
225 else {
Emeric Bruned760922010-10-22 17:59:25 +0200226 /* 2) look for the addr/port delimiter, it's the last colon. */
227 if ((range = strrchr(str, ':')) == NULL) {
228 Alert("Missing port number: '%s'\n", str);
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231
232 *range++ = 0;
233
234 if (strrchr(str, ':') != NULL) {
235 /* IPv6 address contains ':' */
236 memset(&ss, 0, sizeof(ss));
237 ss.ss_family = AF_INET6;
238
239 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
240 Alert("Invalid server address: '%s'\n", str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Emeric Bruned760922010-10-22 17:59:25 +0200244 else {
245 memset(&ss, 0, sizeof(ss));
246 ss.ss_family = AF_INET;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Emeric Bruned760922010-10-22 17:59:25 +0200248 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
249 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
250 }
251 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
252 struct hostent *he;
253
254 if ((he = gethostbyname(str)) == NULL) {
255 Alert("Invalid server name: '%s'\n", str);
256 goto fail;
257 }
258 else
259 ((struct sockaddr_in *)&ss)->sin_addr =
260 *(struct in_addr *) *(he->h_addr_list);
261 }
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Emeric Bruned760922010-10-22 17:59:25 +0200264 /* 3) look for the port-end delimiter */
265 if ((c = strchr(range, '-')) != NULL) {
266 *c++ = 0;
267 end = atol(c);
268 }
269 else {
270 end = atol(range);
271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
Emeric Bruned760922010-10-22 17:59:25 +0200273 port = atol(range);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
Emeric Bruned760922010-10-22 17:59:25 +0200275 if (port < 1 || port > 65535) {
276 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
277 goto fail;
278 }
279
280 if (end < 1 || end > 65535) {
281 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
282 goto fail;
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 }
285
286 for (; port <= end; port++) {
287 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 l->next = curproxy->listen;
289 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
291 l->fd = -1;
292 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 l->state = LI_INIT;
294
Emeric Bruned760922010-10-22 17:59:25 +0200295 if(ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100297 tcpv4_add_listener(l);
298 }
Emeric Bruned760922010-10-22 17:59:25 +0200299 else if (ss.ss_family == AF_INET6) {
300 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
301 tcpv6_add_listener(l);
302 }
303 else {
304 l->perm.ux.gid = l->perm.ux.uid = -1;
305 l->perm.ux.mode = 0;
306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320/*
321 * Sends a warning if proxy <proxy> does not have at least one of the
322 * capabilities in <cap>. An optionnal <hint> may be added at the end
323 * of the warning to help the user. Returns 1 if a warning was emitted
324 * or 0 if the condition is valid.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100327{
328 char *msg;
329
330 switch (cap) {
331 case PR_CAP_BE: msg = "no backend"; break;
332 case PR_CAP_FE: msg = "no frontend"; break;
333 case PR_CAP_RS: msg = "no ruleset"; break;
334 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
335 default: msg = "not enough"; break;
336 }
337
338 if (!(proxy->cap & cap)) {
339 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100340 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100341 return 1;
342 }
343 return 0;
344}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345
Willy Tarreau61d18892009-03-31 10:49:21 +0200346/* Report a warning if a rule is placed after a 'block' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (!LIST_ISEMPTY(&proxy->block_cond)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' 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 reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' 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 rule is placed after a reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
415 warnif_rule_after_reqadd(proxy, file, line, arg) ||
416 warnif_rule_after_redirect(proxy, file, line, arg) ||
417 warnif_rule_after_use_backend(proxy, file, line, arg);
418}
419
420/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100421int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200422{
423 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
424 warnif_rule_after_redirect(proxy, file, line, arg) ||
425 warnif_rule_after_use_backend(proxy, file, line, arg);
426}
427
428/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 return warnif_rule_after_redirect(proxy, file, line, arg) ||
432 warnif_rule_after_use_backend(proxy, file, line, arg);
433}
434
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100435/* Report it if a request ACL condition uses some response-only parameters. It
436 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
447 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100452/* Report it if a request ACL condition uses some request-only volatile parameters.
453 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
454 * Note that <cond> may be NULL and then will be ignored.
455 */
456static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
457{
458 struct acl *acl;
459
460 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
461 return 0;
462
463 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
464 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
465 file, line, acl ? acl->name : "(unknown)");
466 return ERR_WARN;
467}
468
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100469
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 * parse a line in a <global> section. Returns the error code, 0 if OK, or
472 * any combination of :
473 * - ERR_ABORT: must abort ASAP
474 * - ERR_FATAL: we can continue parsing but not start the service
475 * - ERR_WARN: a warning has been emitted
476 * - ERR_ALERT: an alert has been emitted
477 * Only the two first ones can stop processing, the two others are just
478 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200480int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481{
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483
484 if (!strcmp(args[0], "global")) { /* new section */
485 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 }
488 else if (!strcmp(args[0], "daemon")) {
489 global.mode |= MODE_DAEMON;
490 }
491 else if (!strcmp(args[0], "debug")) {
492 global.mode |= MODE_DEBUG;
493 }
494 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100495 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200497 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100498 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200499 }
500 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100501 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100504 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100506 else if (!strcmp(args[0], "nosplice")) {
507 global.tune.options &= ~GTUNE_USE_SPLICE;
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "quiet")) {
510 global.mode |= MODE_QUIET;
511 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200512 else if (!strcmp(args[0], "tune.maxpollevents")) {
513 if (global.tune.maxpollevents != 0) {
514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT;
516 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200517 }
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200522 }
523 global.tune.maxpollevents = atol(args[1]);
524 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100525 else if (!strcmp(args[0], "tune.maxaccept")) {
526 if (global.tune.maxaccept != 0) {
527 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200528 err_code |= ERR_ALERT;
529 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100530 }
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100535 }
536 global.tune.maxaccept = atol(args[1]);
537 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200538 else if (!strcmp(args[0], "tune.chksize")) {
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT | ERR_FATAL;
542 goto out;
543 }
544 global.tune.chksize = atol(args[1]);
545 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200546 else if (!strcmp(args[0], "tune.bufsize")) {
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.bufsize = atol(args[1]);
553 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
554 global.tune.maxrewrite = global.tune.bufsize / 2;
555 }
556 else if (!strcmp(args[0], "tune.maxrewrite")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.maxrewrite = atol(args[1]);
563 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
564 global.tune.maxrewrite = global.tune.bufsize / 2;
565 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100566 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
567 if (global.tune.client_rcvbuf != 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.client_rcvbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
580 if (global.tune.server_rcvbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_rcvbuf = atol(args[1]);
591 }
592 else if (!strcmp(args[0], "tune.sndbuf.client")) {
593 if (global.tune.client_sndbuf != 0) {
594 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT;
596 goto out;
597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.client_sndbuf = atol(args[1]);
604 }
605 else if (!strcmp(args[0], "tune.sndbuf.server")) {
606 if (global.tune.server_sndbuf != 0) {
607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT;
609 goto out;
610 }
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.server_sndbuf = atol(args[1]);
617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 else if (!strcmp(args[0], "uid")) {
619 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 global.uid = atol(args[1]);
630 }
631 else if (!strcmp(args[0], "gid")) {
632 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.gid = atol(args[1]);
643 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 /* user/group name handling */
645 else if (!strcmp(args[0], "user")) {
646 struct passwd *ha_user;
647 if (global.uid != 0) {
648 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 errno = 0;
653 ha_user = getpwnam(args[1]);
654 if (ha_user != NULL) {
655 global.uid = (int)ha_user->pw_uid;
656 }
657 else {
658 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 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 }
662 else if (!strcmp(args[0], "group")) {
663 struct group *ha_group;
664 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200665 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 errno = 0;
670 ha_group = getgrnam(args[1]);
671 if (ha_group != NULL) {
672 global.gid = (int)ha_group->gr_gid;
673 }
674 else {
675 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 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200677 }
678 }
679 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nbproc")) {
681 if (global.nbproc != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 global.nbproc = atol(args[1]);
692 }
693 else if (!strcmp(args[0], "maxconn")) {
694 if (global.maxconn != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.maxconn = atol(args[1]);
705#ifdef SYSTEM_MAXCONN
706 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
707 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);
708 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711#endif /* SYSTEM_MAXCONN */
712 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100713 else if (!strcmp(args[0], "maxpipes")) {
714 if (global.maxpipes != 0) {
715 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200716 err_code |= ERR_ALERT;
717 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100718 }
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100723 }
724 global.maxpipes = atol(args[1]);
725 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 else if (!strcmp(args[0], "ulimit-n")) {
727 if (global.rlimit_nofile != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 global.rlimit_nofile = atol(args[1]);
738 }
739 else if (!strcmp(args[0], "chroot")) {
740 if (global.chroot != NULL) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.chroot = strdup(args[1]);
751 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200752 else if (!strcmp(args[0], "description")) {
753 int i, len=0;
754 char *d;
755
756 if (!*args[1]) {
757 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
758 file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762
763 for(i=1; *args[i]; i++)
764 len += strlen(args[i])+1;
765
766 if (global.desc)
767 free(global.desc);
768
769 global.desc = d = (char *)calloc(1, len);
770
771 d += sprintf(d, "%s", args[1]);
772 for(i=2; *args[i]; i++)
773 d += sprintf(d, " %s", args[i]);
774 }
775 else if (!strcmp(args[0], "node")) {
776 int i;
777 char c;
778
779 for (i=0; args[1][i]; i++) {
780 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100781 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
782 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200783 break;
784 }
785
786 if (!i || args[1][i]) {
787 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
788 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793
794 if (global.node)
795 free(global.node);
796
797 global.node = strdup(args[1]);
798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 else if (!strcmp(args[0], "pidfile")) {
800 if (global.pidfile != NULL) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 global.pidfile = strdup(args[1]);
811 }
Emeric Bruned760922010-10-22 17:59:25 +0200812 else if (!strcmp(args[0], "unix-bind")) {
813 int cur_arg = 1;
814 while (*(args[cur_arg])) {
815 if (!strcmp(args[cur_arg], "prefix")) {
816 if (global.unix_bind.prefix != NULL) {
817 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
818 err_code |= ERR_ALERT;
819 cur_arg += 2;
820 continue;
821 }
822
823 if (*(args[cur_arg+1]) == 0) {
824 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.unix_bind.prefix = strdup(args[cur_arg+1]);
829 cur_arg += 2;
830 continue;
831 }
832
833 if (!strcmp(args[cur_arg], "mode")) {
834
835 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
836 cur_arg += 2;
837 continue;
838 }
839
840 if (!strcmp(args[cur_arg], "uid")) {
841
842 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
843 cur_arg += 2;
844 continue;
845 }
846
847 if (!strcmp(args[cur_arg], "gid")) {
848
849 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
850 cur_arg += 2;
851 continue;
852 }
853
854 if (!strcmp(args[cur_arg], "user")) {
855 struct passwd *user;
856
857 user = getpwnam(args[cur_arg + 1]);
858 if (!user) {
859 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
860 file, linenum, args[0], args[cur_arg + 1 ]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864
865 global.unix_bind.ux.uid = user->pw_uid;
866 cur_arg += 2;
867 continue;
868 }
869
870 if (!strcmp(args[cur_arg], "group")) {
871 struct group *group;
872
873 group = getgrnam(args[cur_arg + 1]);
874 if (!group) {
875 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
876 file, linenum, args[0], args[cur_arg + 1 ]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880
881 global.unix_bind.ux.gid = group->gr_gid;
882 cur_arg += 2;
883 continue;
884 }
885
886 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
887 file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100893 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200894 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895
896 if (*(args[1]) == 0 || *(args[2]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901
902 facility = get_log_facility(args[2]);
903 if (facility < 0) {
904 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200905 err_code |= ERR_ALERT | ERR_FATAL;
906 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907 }
908
909 level = 7; /* max syslog level = debug */
910 if (*(args[3])) {
911 level = get_log_level(args[3]);
912 if (level < 0) {
913 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200914 err_code |= ERR_ALERT | ERR_FATAL;
915 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 }
917 }
918
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200919 minlvl = 0; /* limit syslog level to this level (emerg) */
920 if (*(args[4])) {
921 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200923 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
925 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 }
927 }
928
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100930 struct sockaddr_un *sk = str2sun(args[1]);
931 if (!sk) {
932 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
933 args[1], (int)sizeof(sk->sun_path) - 1);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100938 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100939 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100940 struct sockaddr_in *sk = str2sa(args[1]);
941 if (!sk) {
942 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100947 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100948 if (!logsrv.u.in.sin_port)
949 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951
952 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100953 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 global.logfac1 = facility;
955 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200956 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 global.logfac2 = facility;
961 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200962 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 else {
965 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200968 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100969 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
970 char *name;
971 int len;
972
973 if (global.log_send_hostname != NULL) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT;
976 goto out;
977 }
978
979 if (*(args[1]))
980 name = args[1];
981 else
982 name = hostname;
983
984 len = strlen(name);
985
986 /* We'll add a space after the name to respect the log format */
987 free(global.log_send_hostname);
988 global.log_send_hostname = malloc(len + 2);
989 snprintf(global.log_send_hostname, len + 2, "%s ", name);
990 }
Kevinm48936af2010-12-22 16:08:21 +0000991 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
992 if (*(args[1]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
994 err_code |= ERR_ALERT | ERR_FATAL;
995 goto out;
996 }
997 free(global.log_tag);
998 global.log_tag = strdup(args[1]);
999 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001000 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1001 if (global.spread_checks != 0) {
1002 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT;
1004 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 }
1006 if (*(args[1]) == 0) {
1007 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 global.spread_checks = atol(args[1]);
1012 if (global.spread_checks < 0 || global.spread_checks > 50) {
1013 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
1017 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001018 struct cfg_kw_list *kwl;
1019 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001020 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001021
1022 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1023 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1024 if (kwl->kw[index].section != CFG_GLOBAL)
1025 continue;
1026 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1027 /* prepare error message just in case */
1028 snprintf(trash, sizeof(trash),
1029 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1031 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001032 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001033 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001034 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 else if (rc > 0) {
1036 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_WARN;
1038 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001039 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001041 }
1042 }
1043 }
1044
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001048
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 out:
1050 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051}
1052
Willy Tarreau97cb7802010-01-03 20:23:58 +01001053/* Perform the most basic initialization of a proxy :
1054 * memset(), list_init(*), reset_timeouts(*).
1055 */
1056static void init_new_proxy(struct proxy *p)
1057{
1058 memset(p, 0, sizeof(struct proxy));
1059 LIST_INIT(&p->pendconns);
1060 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001061 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001062 LIST_INIT(&p->block_cond);
1063 LIST_INIT(&p->redirect_rules);
1064 LIST_INIT(&p->mon_fail_cond);
1065 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001066 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001067 LIST_INIT(&p->sticking_rules);
1068 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001069 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001070 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001071 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001072 LIST_INIT(&p->req_add);
1073 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001074
1075 /* Timeouts are defined as -1 */
1076 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001077 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001078}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001080void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001082 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 defproxy.mode = PR_MODE_TCP;
1084 defproxy.state = PR_STNEW;
1085 defproxy.maxconn = cfg_maxpconn;
1086 defproxy.conn_retries = CONN_RETRIES;
1087 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001088
1089 defproxy.defsrv.inter = DEF_CHKINTR;
1090 defproxy.defsrv.fastinter = 0;
1091 defproxy.defsrv.downinter = 0;
1092 defproxy.defsrv.rise = DEF_RISETIME;
1093 defproxy.defsrv.fall = DEF_FALLTIME;
1094 defproxy.defsrv.check_port = 0;
1095 defproxy.defsrv.maxqueue = 0;
1096 defproxy.defsrv.minconn = 0;
1097 defproxy.defsrv.maxconn = 0;
1098 defproxy.defsrv.slowstart = 0;
1099 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1100 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1101 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102}
1103
Willy Tarreauade5ec42010-01-28 19:33:49 +01001104
1105static int create_cond_regex_rule(const char *file, int line,
1106 struct proxy *px, int dir, int action, int flags,
1107 const char *cmd, const char *reg, const char *repl,
1108 const char **cond_start)
1109{
1110 regex_t *preg = NULL;
1111 const char *err;
1112 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001113 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114
1115 if (px == &defproxy) {
1116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto err;
1119 }
1120
1121 if (*reg == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1128 err_code |= ERR_WARN;
1129
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 if (cond_start &&
1131 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1132 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1133 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1134 file, line, cmd);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138 }
1139 else if (cond_start && **cond_start) {
1140 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1141 file, line, cmd, *cond_start);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto err;
1144 }
1145
1146 if (dir == ACL_DIR_REQ)
1147 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001148 else
1149 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001150
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 preg = calloc(1, sizeof(regex_t));
1152 if (!preg) {
1153 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1154 err_code = ERR_ALERT | ERR_FATAL;
1155 goto err;
1156 }
1157
1158 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1159 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1160 err_code = ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
1164 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001165 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 if (repl && err) {
1167 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1168 file, line, cmd, *err);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto err;
1171 }
1172
1173 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1174 err_code |= ERR_WARN;
1175
1176 return err_code;
1177 err:
1178 free(preg);
1179 return err_code;
1180}
1181
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001184 * Returns the error code, 0 if OK, or any combination of :
1185 * - ERR_ABORT: must abort ASAP
1186 * - ERR_FATAL: we can continue parsing but not start the service
1187 * - ERR_WARN: a warning has been emitted
1188 * - ERR_ALERT: an alert has been emitted
1189 * Only the two first ones can stop processing, the two others are just
1190 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001192int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1193{
1194 static struct peers *curpeers = NULL;
1195 struct peer *newpeer = NULL;
1196 const char *err;
1197 int err_code = 0;
1198
1199 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1200
1201 err = invalid_char(args[1]);
1202 if (err) {
1203 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1204 file, linenum, *err, args[0], args[1]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 }
1207
1208 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1209 /*
1210 * If there are two proxies with the same name only following
1211 * combinations are allowed:
1212 */
1213 if (strcmp(curpeers->id, args[1]) == 0) {
1214 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1215 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1216 err_code |= ERR_WARN;
1217 }
1218 }
1219
1220 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1221 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1222 err_code |= ERR_ALERT | ERR_ABORT;
1223 goto out;
1224 }
1225
1226 curpeers->next = peers;
1227 peers = curpeers;
1228 curpeers->conf.file = file;
1229 curpeers->conf.line = linenum;
1230 curpeers->last_change = now.tv_sec;
1231 curpeers->id = strdup(args[1]);
1232 }
1233 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1234 char *rport, *raddr;
1235 short realport = 0;
1236 struct sockaddr_in *sk;
1237
1238 if (!*args[2]) {
1239 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1240 file, linenum, args[0]);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244
1245 err = invalid_char(args[1]);
1246 if (err) {
1247 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1248 file, linenum, *err, args[1]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252
1253 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1254 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1255 err_code |= ERR_ALERT | ERR_ABORT;
1256 goto out;
1257 }
1258
1259 /* the peers are linked backwards first */
1260 curpeers->count++;
1261 newpeer->next = curpeers->remote;
1262 curpeers->remote = newpeer;
1263 newpeer->peers = curpeers;
1264 newpeer->conf.file = file;
1265 newpeer->conf.line = linenum;
1266
1267 newpeer->last_change = now.tv_sec;
1268 newpeer->id = strdup(args[1]);
1269
1270 raddr = strdup(args[2]);
1271 rport = strchr(raddr, ':');
1272 if (rport) {
1273 *rport++ = 0;
1274 realport = atol(rport);
1275 }
1276 if (!realport) {
1277 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
1281
1282 sk = str2sa(raddr);
1283 free(raddr);
1284 if (!sk) {
1285 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 newpeer->addr = *sk;
1290 newpeer->addr.sin_port = htons(realport);
1291
1292 if (strcmp(newpeer->id, localpeer) == 0) {
1293 /* Current is local peer, it define a frontend */
1294 newpeer->local = 1;
1295
1296 if (!curpeers->peers_fe) {
1297 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1299 err_code |= ERR_ALERT | ERR_ABORT;
1300 goto out;
1301 }
1302 curpeers->peers_fe->parent = curpeers;
1303
1304 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1305 LIST_INIT(&(curpeers->peers_fe)->acl);
1306 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1307 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1308 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1309 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1310 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1311 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1312
1313 proxy_reset_timeouts(curpeers->peers_fe);
1314
1315 curpeers->peers_fe->last_change = now.tv_sec;
1316 curpeers->peers_fe->id = strdup(args[1]);
1317 curpeers->peers_fe->cap = PR_CAP_FE;
1318 curpeers->peers_fe->maxconn = 65000;
1319 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1320 curpeers->peers_fe->timeout.connect = 5000;
1321 curpeers->peers_fe->accept = peer_accept;
1322 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1323 if (!str2listener(args[2], curpeers->peers_fe)) {
1324 err_code |= ERR_FATAL;
1325 goto out;
1326 }
1327 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1328 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1329 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1330 curpeers->peers_fe->listen->accept = session_accept;
1331 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1332 curpeers->peers_fe->listen->handler = process_session;
1333 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1334 }
1335 }
1336 } /* neither "peer" nor "peers" */
1337 else if (*args[0] != 0) {
1338 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342
1343out:
1344 return err_code;
1345}
1346
1347
Willy Tarreau3842f002009-06-14 11:39:52 +02001348int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349{
1350 static struct proxy *curproxy = NULL;
1351 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001352 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001353 int rc;
1354 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001355 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001356 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357
Willy Tarreau977b8e42006-12-29 14:19:17 +01001358 if (!strcmp(args[0], "listen"))
1359 rc = PR_CAP_LISTEN;
1360 else if (!strcmp(args[0], "frontend"))
1361 rc = PR_CAP_FE | PR_CAP_RS;
1362 else if (!strcmp(args[0], "backend"))
1363 rc = PR_CAP_BE | PR_CAP_RS;
1364 else if (!strcmp(args[0], "ruleset"))
1365 rc = PR_CAP_RS;
1366 else
1367 rc = PR_CAP_NONE;
1368
1369 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 if (!*args[1]) {
1371 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1372 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_ABORT;
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001377
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001378 err = invalid_char(args[1]);
1379 if (err) {
1380 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1381 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001383 }
1384
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001385 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1386 /*
1387 * If there are two proxies with the same name only following
1388 * combinations are allowed:
1389 *
1390 * listen backend frontend ruleset
1391 * listen - - - -
1392 * backend - - OK -
1393 * frontend - OK - -
1394 * ruleset - - - -
1395 */
1396
1397 if (!strcmp(curproxy->id, args[1]) &&
1398 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1399 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001400 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1401 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1402 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001403 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001404 }
1405 }
1406
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001409 err_code |= ERR_ALERT | ERR_ABORT;
1410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001412
Willy Tarreau97cb7802010-01-03 20:23:58 +01001413 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 curproxy->next = proxy;
1415 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001416 curproxy->conf.file = file;
1417 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001418 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421
1422 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001424 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001425 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001426 err_code |= ERR_FATAL;
1427 goto out;
1428 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001429 new = curproxy->listen;
1430 while (new != last) {
1431 new->conf.file = file;
1432 new->conf.line = linenum;
1433 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001434 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 }
1437
1438 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001439 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001440 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001441
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001444 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001445 curproxy->no_options = defproxy.no_options;
1446 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001447 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001448 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001449 curproxy->except_net = defproxy.except_net;
1450 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001451 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001452 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001454 if (defproxy.fwdfor_hdr_len) {
1455 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1456 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1457 }
1458
Willy Tarreaub86db342009-11-30 11:50:16 +01001459 if (defproxy.orgto_hdr_len) {
1460 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1461 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1462 }
1463
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (curproxy->cap & PR_CAP_FE) {
1465 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001466 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001467 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468
1469 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001470 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1471 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472
1473 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475
Willy Tarreau977b8e42006-12-29 14:19:17 +01001476 if (curproxy->cap & PR_CAP_BE) {
1477 curproxy->fullconn = defproxy.fullconn;
1478 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001480 if (defproxy.check_req) {
1481 curproxy->check_req = calloc(1, defproxy.check_len);
1482 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1483 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001484 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 if (defproxy.cookie_name)
1487 curproxy->cookie_name = strdup(defproxy.cookie_name);
1488 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001489 if (defproxy.cookie_domain)
1490 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001491
Willy Tarreau31936852010-10-06 16:59:56 +02001492 if (defproxy.cookie_maxidle)
1493 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1494
1495 if (defproxy.cookie_maxlife)
1496 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1497
Emeric Brun647caf12009-06-30 17:57:00 +02001498 if (defproxy.rdp_cookie_name)
1499 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1500 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1501
Willy Tarreau01732802007-11-01 22:48:15 +01001502 if (defproxy.url_param_name)
1503 curproxy->url_param_name = strdup(defproxy.url_param_name);
1504 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001505
Benoitaffb4812009-03-25 13:02:10 +01001506 if (defproxy.hh_name)
1507 curproxy->hh_name = strdup(defproxy.hh_name);
1508 curproxy->hh_len = defproxy.hh_len;
1509 curproxy->hh_match_domain = defproxy.hh_match_domain;
1510
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001511 if (defproxy.iface_name)
1512 curproxy->iface_name = strdup(defproxy.iface_name);
1513 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001516 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001517 if (defproxy.capture_name)
1518 curproxy->capture_name = strdup(defproxy.capture_name);
1519 curproxy->capture_namelen = defproxy.capture_namelen;
1520 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522
Willy Tarreau977b8e42006-12-29 14:19:17 +01001523 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001524 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001525 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001526 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001527 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001528 curproxy->uri_auth = defproxy.uri_auth;
1529 curproxy->mon_net = defproxy.mon_net;
1530 curproxy->mon_mask = defproxy.mon_mask;
1531 if (defproxy.monitor_uri)
1532 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1533 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001534 if (defproxy.defbe.name)
1535 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 }
1537
1538 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001539 curproxy->timeout.connect = defproxy.timeout.connect;
1540 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001541 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001542 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001543 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001544 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001545 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001546 curproxy->source_addr = defproxy.source_addr;
1547 }
1548
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 curproxy->mode = defproxy.mode;
1550 curproxy->logfac1 = defproxy.logfac1;
1551 curproxy->logsrv1 = defproxy.logsrv1;
1552 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001553 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 curproxy->logfac2 = defproxy.logfac2;
1555 curproxy->logsrv2 = defproxy.logsrv2;
1556 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001557 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001559 curproxy->conf.used_listener_id = EB_ROOT;
1560 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001561
Willy Tarreau93893792009-07-23 13:19:11 +02001562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 }
1564 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1565 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001566 /* FIXME-20070101: we should do this too at the end of the
1567 * config parsing to free all default values.
1568 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001569 free(defproxy.check_req);
1570 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001571 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001572 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001573 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001574 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001575 free(defproxy.capture_name);
1576 free(defproxy.monitor_uri);
1577 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001578 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001579 free(defproxy.fwdfor_hdr_name);
1580 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001581 free(defproxy.orgto_hdr_name);
1582 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001583
Willy Tarreaua534fea2008-08-03 12:19:50 +02001584 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001585 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001586
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 /* we cannot free uri_auth because it might already be used */
1588 init_default_instance();
1589 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 }
1593 else if (curproxy == NULL) {
1594 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 }
1598
Willy Tarreau977b8e42006-12-29 14:19:17 +01001599
1600 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001602 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001603 int cur_arg;
1604
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 if (curproxy == &defproxy) {
1606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001611 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612
Emeric Bruned760922010-10-22 17:59:25 +02001613 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001614 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001619
1620 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001621
1622 /* NOTE: the following line might create several listeners if there
1623 * are comma-separated IPs or port ranges. So all further processing
1624 * will have to be applied to all listeners created after last_listen.
1625 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001626 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
1629 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001630
Willy Tarreau90a570f2009-10-04 20:54:54 +02001631 new_listen = curproxy->listen;
1632 while (new_listen != last_listen) {
1633 new_listen->conf.file = file;
1634 new_listen->conf.line = linenum;
1635 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001636 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001637 }
1638
Emeric Bruned760922010-10-22 17:59:25 +02001639 /* Set default global rights and owner for unix bind */
1640 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1641 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1642 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001643 cur_arg = 2;
1644 while (*(args[cur_arg])) {
1645 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1646#ifdef SO_BINDTODEVICE
1647 struct listener *l;
1648
Emeric Bruned760922010-10-22 17:59:25 +02001649 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1650 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1651 file, linenum, args[0], args[cur_arg]);
1652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
1654 }
1655
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001656 if (!*args[cur_arg + 1]) {
1657 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001661 }
1662
1663 for (l = curproxy->listen; l != last_listen; l = l->next)
1664 l->interface = strdup(args[cur_arg + 1]);
1665
1666 global.last_checks |= LSTCHK_NETADM;
1667
1668 cur_arg += 2;
1669 continue;
1670#else
1671 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1672 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
1674 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001675#endif
1676 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001677 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1678#ifdef TCP_MAXSEG
1679 struct listener *l;
1680 int mss;
1681
Emeric Bruned760922010-10-22 17:59:25 +02001682 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1683 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1684 file, linenum, args[0], args[cur_arg]);
1685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
1687 }
1688
Willy Tarreaube1b9182009-06-14 18:48:19 +02001689 if (!*args[cur_arg + 1]) {
1690 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1691 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001692 err_code |= ERR_ALERT | ERR_FATAL;
1693 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001694 }
1695
Willy Tarreau48a7e722010-12-24 15:26:39 +01001696 mss = atoi(args[cur_arg + 1]);
1697 if (!mss || abs(mss) > 65535) {
1698 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001702 }
1703
1704 for (l = curproxy->listen; l != last_listen; l = l->next)
1705 l->maxseg = mss;
1706
1707 cur_arg += 2;
1708 continue;
1709#else
1710 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1711 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001714#endif
1715 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001716
1717 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1718#ifdef TCP_DEFER_ACCEPT
1719 struct listener *l;
1720
1721 for (l = curproxy->listen; l != last_listen; l = l->next)
1722 l->options |= LI_O_DEF_ACCEPT;
1723
1724 cur_arg ++;
1725 continue;
1726#else
1727 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1728 file, linenum, args[0], args[cur_arg]);
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
1731#endif
1732 }
1733
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001734 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001735#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001736 struct listener *l;
1737
Emeric Bruned760922010-10-22 17:59:25 +02001738 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1739 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1740 file, linenum, args[0], args[cur_arg]);
1741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
1743 }
1744
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001745 for (l = curproxy->listen; l != last_listen; l = l->next)
1746 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001747
1748 cur_arg ++;
1749 continue;
1750#else
1751 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1752 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001755#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001756 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001757
Willy Tarreau8a956912010-10-15 14:27:08 +02001758 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1759 struct listener *l;
1760
1761 for (l = curproxy->listen; l != last_listen; l = l->next)
1762 l->options |= LI_O_ACC_PROXY;
1763
1764 cur_arg ++;
1765 continue;
1766 }
1767
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001768 if (!strcmp(args[cur_arg], "name")) {
1769 struct listener *l;
1770
1771 for (l = curproxy->listen; l != last_listen; l = l->next)
1772 l->name = strdup(args[cur_arg + 1]);
1773
1774 cur_arg += 2;
1775 continue;
1776 }
1777
1778 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001779 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001780 struct listener *l;
1781
1782 if (curproxy->listen->next != last_listen) {
1783 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1784 file, linenum, args[cur_arg]);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788
1789 if (!*args[cur_arg + 1]) {
1790 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1791 file, linenum, args[cur_arg]);
1792 err_code |= ERR_ALERT | ERR_FATAL;
1793 goto out;
1794 }
1795
1796 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001797 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001798
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001799 if (curproxy->listen->luid <= 0) {
1800 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001801 file, linenum);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804 }
1805
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001806 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1807 if (node) {
1808 l = container_of(node, struct listener, conf.id);
1809 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1810 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
1814 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1815
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001816 cur_arg += 2;
1817 continue;
1818 }
1819
Emeric Bruned760922010-10-22 17:59:25 +02001820 if (!strcmp(args[cur_arg], "mode")) {
1821
1822 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1823 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1824 file, linenum, args[0], args[cur_arg]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
1828
1829 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1830
1831 cur_arg += 2;
1832 continue;
1833 }
1834
1835 if (!strcmp(args[cur_arg], "uid")) {
1836
1837 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1838 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1839 file, linenum, args[0], args[cur_arg]);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843
1844 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1845 cur_arg += 2;
1846 continue;
1847 }
1848
1849 if (!strcmp(args[cur_arg], "gid")) {
1850
1851 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1852 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1853 file, linenum, args[0], args[cur_arg]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
1858 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1859 cur_arg += 2;
1860 continue;
1861 }
1862
1863 if (!strcmp(args[cur_arg], "user")) {
1864 struct passwd *user;
1865
1866 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1867 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1868 file, linenum, args[0], args[cur_arg]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872 user = getpwnam(args[cur_arg + 1]);
1873 if (!user) {
1874 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1875 file, linenum, args[0], args[cur_arg + 1 ]);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879
1880 curproxy->listen->perm.ux.uid = user->pw_uid;
1881 cur_arg += 2;
1882 continue;
1883 }
1884
1885 if (!strcmp(args[cur_arg], "group")) {
1886 struct group *group;
1887
1888 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1889 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1890 file, linenum, args[0], args[cur_arg]);
1891 err_code |= ERR_ALERT | ERR_FATAL;
1892 goto out;
1893 }
1894 group = getgrnam(args[cur_arg + 1]);
1895 if (!group) {
1896 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1897 file, linenum, args[0], args[cur_arg + 1 ]);
1898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
1900 }
1901
1902 curproxy->listen->perm.ux.gid = group->gr_gid;
1903 cur_arg += 2;
1904 continue;
1905 }
1906
Willy Tarreau8a956912010-10-15 14:27:08 +02001907 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 +01001908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001911 }
Willy Tarreau93893792009-07-23 13:19:11 +02001912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 }
1914 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1915 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1916 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1917 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001918 err_code |= ERR_ALERT | ERR_FATAL;
1919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 /* flush useless bits */
1925 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001928 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931
Willy Tarreau1c47f852006-07-09 08:22:27 +02001932 if (!*args[1]) {
1933 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1934 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001937 }
1938
Willy Tarreaua534fea2008-08-03 12:19:50 +02001939 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001940 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001941 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001942 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001943 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1944
Willy Tarreau93893792009-07-23 13:19:11 +02001945 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1948 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1949 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1950 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1951 else {
1952 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 }
1956 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001957 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001958 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001959
1960 if (curproxy == &defproxy) {
1961 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001965 }
1966
1967 if (!*args[1]) {
1968 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001972 }
1973
1974 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001975 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001976
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001977 if (curproxy->uuid <= 0) {
1978 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001979 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001982 }
1983
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001984 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1985 if (node) {
1986 struct proxy *target = container_of(node, struct proxy, conf.id);
1987 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1988 file, linenum, proxy_type_str(curproxy), curproxy->id,
1989 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
1992 }
1993 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001994 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001995 else if (!strcmp(args[0], "description")) {
1996 int i, len=0;
1997 char *d;
1998
Cyril Bonté99ed3272010-01-24 23:29:44 +01001999 if (curproxy == &defproxy) {
2000 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2001 file, linenum, args[0]);
2002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
2004 }
2005
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002006 if (!*args[1]) {
2007 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2008 file, linenum, args[0]);
2009 return -1;
2010 }
2011
2012 for(i=1; *args[i]; i++)
2013 len += strlen(args[i])+1;
2014
2015 d = (char *)calloc(1, len);
2016 curproxy->desc = d;
2017
2018 d += sprintf(d, "%s", args[1]);
2019 for(i=2; *args[i]; i++)
2020 d += sprintf(d, " %s", args[i]);
2021
2022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2024 curproxy->state = PR_STSTOPPED;
2025 }
2026 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2027 curproxy->state = PR_STNEW;
2028 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002029 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2030 int cur_arg = 1;
2031 unsigned int set = 0;
2032
2033 while (*args[cur_arg]) {
2034 int u;
2035 if (strcmp(args[cur_arg], "all") == 0) {
2036 set = 0;
2037 break;
2038 }
2039 else if (strcmp(args[cur_arg], "odd") == 0) {
2040 set |= 0x55555555;
2041 }
2042 else if (strcmp(args[cur_arg], "even") == 0) {
2043 set |= 0xAAAAAAAA;
2044 }
2045 else {
2046 u = str2uic(args[cur_arg]);
2047 if (u < 1 || u > 32) {
2048 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002052 }
2053 if (u > global.nbproc) {
2054 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2055 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002057 }
2058 set |= 1 << (u - 1);
2059 }
2060 cur_arg++;
2061 }
2062 curproxy->bind_proc = set;
2063 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002064 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002065 if (curproxy == &defproxy) {
2066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002069 }
2070
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002071 err = invalid_char(args[1]);
2072 if (err) {
2073 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2074 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002076 }
2077
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002078 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2079 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2080 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002083 }
2084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2086 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 if (*(args[1]) == 0) {
2092 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002097
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002098 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002099 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002100 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002101 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002102 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 curproxy->cookie_name = strdup(args[1]);
2104 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002105
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 cur_arg = 2;
2107 while (*(args[cur_arg])) {
2108 if (!strcmp(args[cur_arg], "rewrite")) {
2109 curproxy->options |= PR_O_COOK_RW;
2110 }
2111 else if (!strcmp(args[cur_arg], "indirect")) {
2112 curproxy->options |= PR_O_COOK_IND;
2113 }
2114 else if (!strcmp(args[cur_arg], "insert")) {
2115 curproxy->options |= PR_O_COOK_INS;
2116 }
2117 else if (!strcmp(args[cur_arg], "nocache")) {
2118 curproxy->options |= PR_O_COOK_NOC;
2119 }
2120 else if (!strcmp(args[cur_arg], "postonly")) {
2121 curproxy->options |= PR_O_COOK_POST;
2122 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002123 else if (!strcmp(args[cur_arg], "preserve")) {
2124 curproxy->options2 |= PR_O2_COOK_PSV;
2125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 else if (!strcmp(args[cur_arg], "prefix")) {
2127 curproxy->options |= PR_O_COOK_PFX;
2128 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002129 else if (!strcmp(args[cur_arg], "domain")) {
2130 if (!*args[cur_arg + 1]) {
2131 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2132 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002135 }
2136
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002137 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002138 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002139 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2140 " dots nor does not start with a dot."
2141 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002142 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002143 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002144 }
2145
2146 err = invalid_domainchar(args[cur_arg + 1]);
2147 if (err) {
2148 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2149 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002152 }
2153
Willy Tarreau68a897b2009-12-03 23:28:34 +01002154 if (!curproxy->cookie_domain) {
2155 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2156 } else {
2157 /* one domain was already specified, add another one by
2158 * building the string which will be returned along with
2159 * the cookie.
2160 */
2161 char *new_ptr;
2162 int new_len = strlen(curproxy->cookie_domain) +
2163 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2164 new_ptr = malloc(new_len);
2165 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2166 free(curproxy->cookie_domain);
2167 curproxy->cookie_domain = new_ptr;
2168 }
Willy Tarreau31936852010-10-06 16:59:56 +02002169 cur_arg++;
2170 }
2171 else if (!strcmp(args[cur_arg], "maxidle")) {
2172 unsigned int maxidle;
2173 const char *res;
2174
2175 if (!*args[cur_arg + 1]) {
2176 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2177 file, linenum, args[cur_arg]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181
2182 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2183 if (res) {
2184 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2185 file, linenum, *res, args[cur_arg]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189 curproxy->cookie_maxidle = maxidle;
2190 cur_arg++;
2191 }
2192 else if (!strcmp(args[cur_arg], "maxlife")) {
2193 unsigned int maxlife;
2194 const char *res;
2195
2196 if (!*args[cur_arg + 1]) {
2197 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2198 file, linenum, args[cur_arg]);
2199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
2202
2203 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2204 if (res) {
2205 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2206 file, linenum, *res, args[cur_arg]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002211 cur_arg++;
2212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002214 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 +02002215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }
2219 cur_arg++;
2220 }
2221 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2222 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2223 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 }
2226
2227 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2228 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2229 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002232
2233 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2234 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2235 file, linenum);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002239 else if (!strcmp(args[0], "persist")) { /* persist */
2240 if (*(args[1]) == 0) {
2241 Alert("parsing [%s:%d] : missing persist method.\n",
2242 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002245 }
2246
2247 if (!strncmp(args[1], "rdp-cookie", 10)) {
2248 curproxy->options2 |= PR_O2_RDPC_PRST;
2249
Emeric Brunb982a3d2010-01-04 15:45:53 +01002250 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002251 const char *beg, *end;
2252
2253 beg = args[1] + 11;
2254 end = strchr(beg, ')');
2255
2256 if (!end || end == beg) {
2257 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002261 }
2262
2263 free(curproxy->rdp_cookie_name);
2264 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2265 curproxy->rdp_cookie_len = end-beg;
2266 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002267 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002268 free(curproxy->rdp_cookie_name);
2269 curproxy->rdp_cookie_name = strdup("msts");
2270 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2271 }
2272 else { /* syntax */
2273 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002277 }
2278 }
2279 else {
2280 Alert("parsing [%s:%d] : unknown persist method.\n",
2281 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002284 }
2285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002287 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002289 if (curproxy == &defproxy) {
2290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002299 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 }
2304 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->appsession_name = strdup(args[1]);
2307 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2308 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002309 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2310 if (err) {
2311 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2312 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002315 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002316 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002317
Willy Tarreau51041c72007-09-09 21:56:53 +02002318 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_ABORT;
2321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002323
2324 cur_arg = 6;
2325 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002326 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2327 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002328 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002329 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002330 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002331 } else if (!strcmp(args[cur_arg], "prefix")) {
2332 curproxy->options2 |= PR_O2_AS_PFX;
2333 } else if (!strcmp(args[cur_arg], "mode")) {
2334 if (!*args[cur_arg + 1]) {
2335 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2336 file, linenum, args[0], args[cur_arg]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 cur_arg++;
2342 if (!strcmp(args[cur_arg], "query-string")) {
2343 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2344 curproxy->options2 |= PR_O2_AS_M_QS;
2345 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2346 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2347 curproxy->options2 |= PR_O2_AS_M_PP;
2348 } else {
2349 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002354 cur_arg++;
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 } /* Url App Session */
2357 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002358 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002360
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002362 if (curproxy == &defproxy) {
2363 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
2366 }
2367
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 if (*(args[4]) == 0) {
2369 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002374 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 curproxy->capture_name = strdup(args[2]);
2376 curproxy->capture_namelen = strlen(curproxy->capture_name);
2377 curproxy->capture_len = atol(args[4]);
2378 if (curproxy->capture_len >= CAPTURE_LEN) {
2379 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2380 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 curproxy->capture_len = CAPTURE_LEN - 1;
2383 }
2384 curproxy->to_log |= LW_COOKIE;
2385 }
2386 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2387 struct cap_hdr *hdr;
2388
2389 if (curproxy == &defproxy) {
2390 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 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394
2395 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2396 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2397 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401
2402 hdr = calloc(sizeof(struct cap_hdr), 1);
2403 hdr->next = curproxy->req_cap;
2404 hdr->name = strdup(args[3]);
2405 hdr->namelen = strlen(args[3]);
2406 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002407 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 hdr->index = curproxy->nb_req_cap++;
2409 curproxy->req_cap = hdr;
2410 curproxy->to_log |= LW_REQHDR;
2411 }
2412 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2413 struct cap_hdr *hdr;
2414
2415 if (curproxy == &defproxy) {
2416 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 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420
2421 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2422 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2423 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427 hdr = calloc(sizeof(struct cap_hdr), 1);
2428 hdr->next = curproxy->rsp_cap;
2429 hdr->name = strdup(args[3]);
2430 hdr->namelen = strlen(args[3]);
2431 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002432 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 hdr->index = curproxy->nb_rsp_cap++;
2434 curproxy->rsp_cap = hdr;
2435 curproxy->to_log |= LW_RSPHDR;
2436 }
2437 else {
2438 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 if (*(args[1]) == 0) {
2449 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 }
2454 curproxy->conn_retries = atol(args[1]);
2455 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002456 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2457 struct req_acl_rule *req_acl;
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
2466 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2467 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2468 file, linenum, args[0]);
2469 err_code |= ERR_WARN;
2470 }
2471
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002472 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002473
2474 if (!req_acl) {
2475 err_code |= ERR_ALERT | ERR_ABORT;
2476 goto out;
2477 }
2478
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002479 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002480 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2481 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002483 if (curproxy == &defproxy) {
2484 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002487 }
2488
Willy Tarreauef6494c2010-01-28 17:12:36 +01002489 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002490 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002494 }
2495
Willy Tarreauef6494c2010-01-28 17:12:36 +01002496 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002497 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2498 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002501 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002502
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002503 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002504 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002505 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002506 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002507 struct redirect_rule *rule;
2508 int cur_arg;
2509 int type = REDIRECT_TYPE_NONE;
2510 int code = 302;
2511 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002512 char *cookie = NULL;
2513 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002514 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002515
Cyril Bonté99ed3272010-01-24 23:29:44 +01002516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 cur_arg = 1;
2523 while (*(args[cur_arg])) {
2524 if (!strcmp(args[cur_arg], "location")) {
2525 if (!*args[cur_arg + 1]) {
2526 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2527 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 }
2531
2532 type = REDIRECT_TYPE_LOCATION;
2533 cur_arg++;
2534 destination = args[cur_arg];
2535 }
2536 else if (!strcmp(args[cur_arg], "prefix")) {
2537 if (!*args[cur_arg + 1]) {
2538 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2539 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002542 }
2543
2544 type = REDIRECT_TYPE_PREFIX;
2545 cur_arg++;
2546 destination = args[cur_arg];
2547 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002548 else if (!strcmp(args[cur_arg], "set-cookie")) {
2549 if (!*args[cur_arg + 1]) {
2550 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2551 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002554 }
2555
2556 cur_arg++;
2557 cookie = args[cur_arg];
2558 cookie_set = 1;
2559 }
2560 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2561 if (!*args[cur_arg + 1]) {
2562 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2563 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002566 }
2567
2568 cur_arg++;
2569 cookie = args[cur_arg];
2570 cookie_set = 0;
2571 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002572 else if (!strcmp(args[cur_arg],"code")) {
2573 if (!*args[cur_arg + 1]) {
2574 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002578 }
2579 cur_arg++;
2580 code = atol(args[cur_arg]);
2581 if (code < 301 || code > 303) {
2582 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2583 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 }
2587 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002588 else if (!strcmp(args[cur_arg],"drop-query")) {
2589 flags |= REDIRECT_FLAG_DROP_QS;
2590 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002591 else if (!strcmp(args[cur_arg],"append-slash")) {
2592 flags |= REDIRECT_FLAG_APPEND_SLASH;
2593 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002594 else if (strcmp(args[cur_arg], "if") == 0 ||
2595 strcmp(args[cur_arg], "unless") == 0) {
2596 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2597 if (!cond) {
2598 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2599 file, linenum, args[0]);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002603 break;
2604 }
2605 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002606 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 +02002607 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002610 }
2611 cur_arg++;
2612 }
2613
2614 if (type == REDIRECT_TYPE_NONE) {
2615 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002619 }
2620
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002621 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2622 rule->cond = cond;
2623 rule->rdr_str = strdup(destination);
2624 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002625 if (cookie) {
2626 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002627 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002628 */
2629 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002630 if (cookie_set) {
2631 rule->cookie_str = malloc(rule->cookie_len + 10);
2632 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2633 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2634 rule->cookie_len += 9;
2635 } else {
2636 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002637 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002638 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2639 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002640 }
2641 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002642 rule->type = type;
2643 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002644 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002645 LIST_INIT(&rule->list);
2646 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002647 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2648 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002650 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002651 struct switching_rule *rule;
2652
Willy Tarreaub099aca2008-10-12 17:26:37 +02002653 if (curproxy == &defproxy) {
2654 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002657 }
2658
Willy Tarreau55ea7572007-06-17 19:56:27 +02002659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002660 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002661
2662 if (*(args[1]) == 0) {
2663 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002666 }
2667
Willy Tarreauef6494c2010-01-28 17:12:36 +01002668 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002669 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2670 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002673 }
2674
Willy Tarreauef6494c2010-01-28 17:12:36 +01002675 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002676 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002677 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680 }
2681
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002682 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002683
Willy Tarreau55ea7572007-06-17 19:56:27 +02002684 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2685 rule->cond = cond;
2686 rule->be.name = strdup(args[1]);
2687 LIST_INIT(&rule->list);
2688 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2689 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002690 else if ((!strcmp(args[0], "force-persist")) ||
2691 (!strcmp(args[0], "ignore-persist"))) {
2692 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002693
2694 if (curproxy == &defproxy) {
2695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699
2700 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2701 err_code |= ERR_WARN;
2702
Willy Tarreauef6494c2010-01-28 17:12:36 +01002703 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002704 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2705 file, linenum, args[0]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
2709
Willy Tarreauef6494c2010-01-28 17:12:36 +01002710 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002711 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2712 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002717 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002718
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002719 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002720 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002721 if (!strcmp(args[0], "force-persist")) {
2722 rule->type = PERSIST_TYPE_FORCE;
2723 } else {
2724 rule->type = PERSIST_TYPE_IGNORE;
2725 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002726 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002727 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002728 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 else if (!strcmp(args[0], "stick-table")) {
2730 int myidx = 1;
2731
Emeric Brun32da3c42010-09-23 18:39:19 +02002732 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002733 curproxy->table.type = (unsigned int)-1;
2734 while (*args[myidx]) {
2735 const char *err;
2736
2737 if (strcmp(args[myidx], "size") == 0) {
2738 myidx++;
2739 if (!*(args[myidx])) {
2740 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2741 file, linenum, args[myidx-1]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
2745 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2746 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2747 file, linenum, *err, args[myidx-1]);
2748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002751 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002752 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002753 else if (strcmp(args[myidx], "peers") == 0) {
2754 myidx++;
2755 if (!*(args[myidx])) {
2756 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2757 file, linenum, args[myidx-1]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761 curproxy->table.peers.name = strdup(args[myidx++]);
2762 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002763 else if (strcmp(args[myidx], "expire") == 0) {
2764 myidx++;
2765 if (!*(args[myidx])) {
2766 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2767 file, linenum, args[myidx-1]);
2768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
2771 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2772 if (err) {
2773 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2774 file, linenum, *err, args[myidx-1]);
2775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002779 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002780 }
2781 else if (strcmp(args[myidx], "nopurge") == 0) {
2782 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002783 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002784 }
2785 else if (strcmp(args[myidx], "type") == 0) {
2786 myidx++;
2787 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2788 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2789 file, linenum, args[myidx]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002793 /* myidx already points to next arg */
2794 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002795 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002796 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002797 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002798
2799 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002800 nw = args[myidx];
2801 while (*nw) {
2802 /* the "store" keyword supports a comma-separated list */
2803 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002804 sa = NULL; /* store arg */
2805 while (*nw && *nw != ',') {
2806 if (*nw == '(') {
2807 *nw = 0;
2808 sa = ++nw;
2809 while (*nw != ')') {
2810 if (!*nw) {
2811 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2812 file, linenum, args[0], cw);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816 nw++;
2817 }
2818 *nw = '\0';
2819 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002820 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002821 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002822 if (*nw)
2823 *nw++ = '\0';
2824 type = stktable_get_data_type(cw);
2825 if (type < 0) {
2826 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2827 file, linenum, args[0], cw);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
Willy Tarreauac782882010-06-20 10:41:54 +02002831
2832 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2833 switch (err) {
2834 case PE_NONE: break;
2835 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002836 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2837 file, linenum, args[0], cw);
2838 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002839 break;
2840
2841 case PE_ARG_MISSING:
2842 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2843 file, linenum, args[0], cw);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846
2847 case PE_ARG_NOT_USED:
2848 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2849 file, linenum, args[0], cw);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852
2853 default:
2854 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2855 file, linenum, args[0], cw);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002858 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002859 }
2860 myidx++;
2861 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002862 else {
2863 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2864 file, linenum, args[myidx]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002868 }
2869
2870 if (!curproxy->table.size) {
2871 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2872 file, linenum);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 if (curproxy->table.type == (unsigned int)-1) {
2878 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2879 file, linenum);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883 }
2884 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002885 struct sticking_rule *rule;
2886 struct pattern_expr *expr;
2887 int myidx = 0;
2888 const char *name = NULL;
2889 int flags;
2890
2891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2898 err_code |= ERR_WARN;
2899 goto out;
2900 }
2901
2902 myidx++;
2903 if ((strcmp(args[myidx], "store") == 0) ||
2904 (strcmp(args[myidx], "store-request") == 0)) {
2905 myidx++;
2906 flags = STK_IS_STORE;
2907 }
2908 else if (strcmp(args[myidx], "store-response") == 0) {
2909 myidx++;
2910 flags = STK_IS_STORE | STK_ON_RSP;
2911 }
2912 else if (strcmp(args[myidx], "match") == 0) {
2913 myidx++;
2914 flags = STK_IS_MATCH;
2915 }
2916 else if (strcmp(args[myidx], "on") == 0) {
2917 myidx++;
2918 flags = STK_IS_MATCH | STK_IS_STORE;
2919 }
2920 else {
2921 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
2926 if (*(args[myidx]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
2931
Emeric Brun485479d2010-09-23 18:02:19 +02002932 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002933 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002934 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (flags & STK_ON_RSP) {
2940 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2941 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2942 file, linenum, args[0], expr->fetch->kw);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946 } else {
2947 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2948 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2949 file, linenum, args[0], expr->fetch->kw);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 }
2954
2955 if (strcmp(args[myidx], "table") == 0) {
2956 myidx++;
2957 name = args[myidx++];
2958 }
2959
Willy Tarreauef6494c2010-01-28 17:12:36 +01002960 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2961 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002962 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2963 file, linenum, args[0]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002967 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002968 else if (*(args[myidx])) {
2969 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2970 file, linenum, args[0], args[myidx]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
Emeric Brun97679e72010-09-23 17:56:44 +02002974 if (flags & STK_ON_RSP)
2975 err_code |= warnif_cond_requires_req(cond, file, linenum);
2976 else
2977 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002978
Emeric Brunb982a3d2010-01-04 15:45:53 +01002979 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2980 rule->cond = cond;
2981 rule->expr = expr;
2982 rule->flags = flags;
2983 rule->table.name = name ? strdup(name) : NULL;
2984 LIST_INIT(&rule->list);
2985 if (flags & STK_ON_RSP)
2986 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2987 else
2988 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002990 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002991 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002993
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2995 curproxy->uri_auth = NULL; /* we must detach from the default config */
2996
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002997 if (!*args[1]) {
2998 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002999 } else if (!strcmp(args[1], "admin")) {
3000 struct stats_admin_rule *rule;
3001
3002 if (curproxy == &defproxy) {
3003 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3009 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3010 err_code |= ERR_ALERT | ERR_ABORT;
3011 goto out;
3012 }
3013
3014 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3015 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3016 file, linenum, args[0], args[1]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3021 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3022 file, linenum, args[0], args[1]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
3026
3027 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3028
3029 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3030 rule->cond = cond;
3031 LIST_INIT(&rule->list);
3032 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 } else if (!strcmp(args[1], "uri")) {
3034 if (*(args[2]) == 0) {
3035 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3039 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_ABORT;
3041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 }
3043 } else if (!strcmp(args[1], "realm")) {
3044 if (*(args[2]) == 0) {
3045 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3049 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_ABORT;
3051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003053 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003054 unsigned interval;
3055
3056 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3057 if (err) {
3058 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3059 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003062 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3063 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_ABORT;
3065 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003066 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003067 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3068 struct req_acl_rule *req_acl;
3069
3070 if (curproxy == &defproxy) {
3071 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075
3076 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3077 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3078 err_code |= ERR_ALERT | ERR_ABORT;
3079 goto out;
3080 }
3081
3082 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3083 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3084 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3085 file, linenum, args[0]);
3086 err_code |= ERR_WARN;
3087 }
3088
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003089 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003090
3091 if (!req_acl) {
3092 err_code |= ERR_ALERT | ERR_ABORT;
3093 goto out;
3094 }
3095
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003096 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003097 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3098
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 } else if (!strcmp(args[1], "auth")) {
3100 if (*(args[2]) == 0) {
3101 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3105 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_ABORT;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 }
3109 } else if (!strcmp(args[1], "scope")) {
3110 if (*(args[2]) == 0) {
3111 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3115 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_ABORT;
3117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 }
3119 } else if (!strcmp(args[1], "enable")) {
3120 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3121 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_ABORT;
3123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003125 } else if (!strcmp(args[1], "hide-version")) {
3126 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3127 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_ABORT;
3129 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003130 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003131 } else if (!strcmp(args[1], "show-legends")) {
3132 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3133 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3134 err_code |= ERR_ALERT | ERR_ABORT;
3135 goto out;
3136 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003137 } else if (!strcmp(args[1], "show-node")) {
3138
3139 if (*args[2]) {
3140 int i;
3141 char c;
3142
3143 for (i=0; args[2][i]; i++) {
3144 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003145 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3146 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003147 break;
3148 }
3149
3150 if (!i || args[2][i]) {
3151 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3152 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3153 file, linenum, args[0], args[1]);
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157 }
3158
3159 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3160 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3161 err_code |= ERR_ALERT | ERR_ABORT;
3162 goto out;
3163 }
3164 } else if (!strcmp(args[1], "show-desc")) {
3165 char *desc = NULL;
3166
3167 if (*args[2]) {
3168 int i, len=0;
3169 char *d;
3170
3171 for(i=2; *args[i]; i++)
3172 len += strlen(args[i])+1;
3173
3174 desc = d = (char *)calloc(1, len);
3175
3176 d += sprintf(d, "%s", args[2]);
3177 for(i=3; *args[i]; i++)
3178 d += sprintf(d, " %s", args[i]);
3179 }
3180
3181 if (!*args[2] && !global.desc)
3182 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3183 file, linenum, args[1]);
3184 else {
3185 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3186 free(desc);
3187 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3188 err_code |= ERR_ALERT | ERR_ABORT;
3189 goto out;
3190 }
3191 free(desc);
3192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003194stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003195 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 +01003196 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200 }
3201 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003202 int optnum;
3203
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003204 if (*(args[1]) == '\0') {
3205 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003210
3211 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3212 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003213 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3214 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3215 file, linenum, cfg_opts[optnum].name);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
Willy Tarreau93893792009-07-23 13:19:11 +02003219 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3220 err_code |= ERR_WARN;
3221 goto out;
3222 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003223
Willy Tarreau3842f002009-06-14 11:39:52 +02003224 curproxy->no_options &= ~cfg_opts[optnum].val;
3225 curproxy->options &= ~cfg_opts[optnum].val;
3226
3227 switch (kwm) {
3228 case KWM_STD:
3229 curproxy->options |= cfg_opts[optnum].val;
3230 break;
3231 case KWM_NO:
3232 curproxy->no_options |= cfg_opts[optnum].val;
3233 break;
3234 case KWM_DEF: /* already cleared */
3235 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003236 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003237
Willy Tarreau93893792009-07-23 13:19:11 +02003238 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003239 }
3240 }
3241
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003242 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3243 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003244 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3245 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3246 file, linenum, cfg_opts2[optnum].name);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
Willy Tarreau93893792009-07-23 13:19:11 +02003250 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3251 err_code |= ERR_WARN;
3252 goto out;
3253 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003254
Willy Tarreau3842f002009-06-14 11:39:52 +02003255 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3256 curproxy->options2 &= ~cfg_opts2[optnum].val;
3257
3258 switch (kwm) {
3259 case KWM_STD:
3260 curproxy->options2 |= cfg_opts2[optnum].val;
3261 break;
3262 case KWM_NO:
3263 curproxy->no_options2 |= cfg_opts2[optnum].val;
3264 break;
3265 case KWM_DEF: /* already cleared */
3266 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003267 }
Willy Tarreau93893792009-07-23 13:19:11 +02003268 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003269 }
3270 }
3271
Willy Tarreau3842f002009-06-14 11:39:52 +02003272 if (kwm != KWM_STD) {
3273 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003274 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003277 }
3278
Emeric Brun3a058f32009-06-30 18:26:00 +02003279 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003281 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003283 if (*(args[2]) != '\0') {
3284 if (!strcmp(args[2], "clf")) {
3285 curproxy->options2 |= PR_O2_CLFLOG;
3286 } else {
3287 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003290 }
3291 }
3292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 else if (!strcmp(args[1], "tcplog"))
3294 /* generate a detailed TCP log */
3295 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 else if (!strcmp(args[1], "tcpka")) {
3297 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003298 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003300
3301 if (curproxy->cap & PR_CAP_FE)
3302 curproxy->options |= PR_O_TCP_CLI_KA;
3303 if (curproxy->cap & PR_CAP_BE)
3304 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
3306 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_WARN;
3309
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003311 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003312 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003313 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003314 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003315 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003316 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003317 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003318 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 if (!*args[2]) { /* no argument */
3320 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3321 curproxy->check_len = strlen(DEF_CHECK_REQ);
3322 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003323 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 curproxy->check_req = (char *)malloc(reqlen);
3325 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003326 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003328 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 if (*args[4])
3330 reqlen += strlen(args[4]);
3331 else
3332 reqlen += strlen("HTTP/1.0");
3333
3334 curproxy->check_req = (char *)malloc(reqlen);
3335 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003336 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003338 }
3339 else if (!strcmp(args[1], "ssl-hello-chk")) {
3340 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003341 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003343
Willy Tarreaua534fea2008-08-03 12:19:50 +02003344 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003345 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003346 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003347 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003348 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003349 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003350 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003351 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
Willy Tarreau23677902007-05-08 23:50:35 +02003353 else if (!strcmp(args[1], "smtpchk")) {
3354 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003355 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003356 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003357 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003358 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003359 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003360 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003361 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003362 curproxy->options |= PR_O_SMTP_CHK;
3363
3364 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3365 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3366 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3367 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3368 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3369 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3370 curproxy->check_req = (char *)malloc(reqlen);
3371 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3372 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3373 } else {
3374 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3375 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3376 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3377 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3378 }
3379 }
3380 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003381 else if (!strcmp(args[1], "pgsql-check")) {
3382 /* use PostgreSQL request to check servers' health */
3383 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3384 err_code |= ERR_WARN;
3385
3386 free(curproxy->check_req);
3387 curproxy->check_req = NULL;
3388 curproxy->options &= ~PR_O_HTTP_CHK;
3389 curproxy->options &= ~PR_O_SMTP_CHK;
3390 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3391 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3392 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3393 curproxy->options2 |= PR_O2_PGSQL_CHK;
3394
3395 if (*(args[2])) {
3396 int cur_arg = 2;
3397
3398 while (*(args[cur_arg])) {
3399 if (strcmp(args[cur_arg], "user") == 0) {
3400 char * packet;
3401 uint32_t packet_len;
3402 uint32_t pv;
3403
3404 /* suboption header - needs additional argument for it */
3405 if (*(args[cur_arg+1]) == 0) {
3406 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3407 file, linenum, args[0], args[1], args[cur_arg]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
3411
3412 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3413 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3414 pv = htonl(0x30000); /* protocol version 3.0 */
3415
3416 packet = (char*) calloc(1, packet_len);
3417
3418 memcpy(packet + 4, &pv, 4);
3419
3420 /* copy "user" */
3421 memcpy(packet + 8, "user", 4);
3422
3423 /* copy username */
3424 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3425
3426 free(curproxy->check_req);
3427 curproxy->check_req = packet;
3428 curproxy->check_len = packet_len;
3429
3430 packet_len = htonl(packet_len);
3431 memcpy(packet, &packet_len, 4);
3432 cur_arg += 2;
3433 } else {
3434 /* unknown suboption - catchall */
3435 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3436 file, linenum, args[0], args[1]);
3437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
3439 }
3440 } /* end while loop */
3441 }
3442 }
3443
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003444 else if (!strcmp(args[1], "mysql-check")) {
3445 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003446 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3447 err_code |= ERR_WARN;
3448
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003449 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003450 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003451 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003452 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003453 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003454 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003455 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003456 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003457
3458 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3459 * const char mysql40_client_auth_pkt[] = {
3460 * "\x0e\x00\x00" // packet length
3461 * "\x01" // packet number
3462 * "\x00\x00" // client capabilities
3463 * "\x00\x00\x01" // max packet
3464 * "haproxy\x00" // username (null terminated string)
3465 * "\x00" // filler (always 0x00)
3466 * "\x01\x00\x00" // packet length
3467 * "\x00" // packet number
3468 * "\x01" // COM_QUIT command
3469 * };
3470 */
3471
3472 if (*(args[2])) {
3473 int cur_arg = 2;
3474
3475 while (*(args[cur_arg])) {
3476 if (strcmp(args[cur_arg], "user") == 0) {
3477 char *mysqluser;
3478 int packetlen, reqlen, userlen;
3479
3480 /* suboption header - needs additional argument for it */
3481 if (*(args[cur_arg+1]) == 0) {
3482 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3483 file, linenum, args[0], args[1], args[cur_arg]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
3487 mysqluser = args[cur_arg + 1];
3488 userlen = strlen(mysqluser);
3489 packetlen = userlen + 7;
3490 reqlen = packetlen + 9;
3491
3492 free(curproxy->check_req);
3493 curproxy->check_req = (char *)calloc(1, reqlen);
3494 curproxy->check_len = reqlen;
3495
3496 snprintf(curproxy->check_req, 4, "%c%c%c",
3497 ((unsigned char) packetlen & 0xff),
3498 ((unsigned char) (packetlen >> 8) & 0xff),
3499 ((unsigned char) (packetlen >> 16) & 0xff));
3500
3501 curproxy->check_req[3] = 1;
3502 curproxy->check_req[8] = 1;
3503 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3504 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3505 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3506 cur_arg += 2;
3507 } else {
3508 /* unknown suboption - catchall */
3509 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3510 file, linenum, args[0], args[1]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514 } /* end while loop */
3515 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003516 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003517 else if (!strcmp(args[1], "ldap-check")) {
3518 /* use LDAP request to check servers' health */
3519 free(curproxy->check_req);
3520 curproxy->check_req = NULL;
3521 curproxy->options &= ~PR_O_HTTP_CHK;
3522 curproxy->options &= ~PR_O_SMTP_CHK;
3523 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3524 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003525 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003526 curproxy->options2 |= PR_O2_LDAP_CHK;
3527
3528 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3529 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3530 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3531 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003532 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003533 int cur_arg;
3534
3535 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3536 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003537 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003538
3539 curproxy->options |= PR_O_FWDFOR;
3540
3541 free(curproxy->fwdfor_hdr_name);
3542 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3543 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3544
3545 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3546 cur_arg = 2;
3547 while (*(args[cur_arg])) {
3548 if (!strcmp(args[cur_arg], "except")) {
3549 /* suboption except - needs additional argument for it */
3550 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3551 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3552 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003555 }
3556 /* flush useless bits */
3557 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003558 cur_arg += 2;
3559 } else if (!strcmp(args[cur_arg], "header")) {
3560 /* suboption header - needs additional argument for it */
3561 if (*(args[cur_arg+1]) == 0) {
3562 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3563 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003566 }
3567 free(curproxy->fwdfor_hdr_name);
3568 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3569 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3570 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003571 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003572 /* unknown suboption - catchall */
3573 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3574 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003577 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003578 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003579 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003580 else if (!strcmp(args[1], "originalto")) {
3581 int cur_arg;
3582
3583 /* insert x-original-to field, but not for the IP address listed as an except.
3584 * set default options (ie: bitfield, header name, etc)
3585 */
3586
3587 curproxy->options |= PR_O_ORGTO;
3588
3589 free(curproxy->orgto_hdr_name);
3590 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3591 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3592
3593 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3594 cur_arg = 2;
3595 while (*(args[cur_arg])) {
3596 if (!strcmp(args[cur_arg], "except")) {
3597 /* suboption except - needs additional argument for it */
3598 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3599 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3600 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003603 }
3604 /* flush useless bits */
3605 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3606 cur_arg += 2;
3607 } else if (!strcmp(args[cur_arg], "header")) {
3608 /* suboption header - needs additional argument for it */
3609 if (*(args[cur_arg+1]) == 0) {
3610 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3611 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003614 }
3615 free(curproxy->orgto_hdr_name);
3616 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3617 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3618 cur_arg += 2;
3619 } else {
3620 /* unknown suboption - catchall */
3621 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3622 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003625 }
3626 } /* end while loop */
3627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 else {
3629 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
Willy Tarreau93893792009-07-23 13:19:11 +02003633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003635 else if (!strcmp(args[0], "default_backend")) {
3636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003638
3639 if (*(args[1]) == 0) {
3640 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003643 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003644 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003645 curproxy->defbe.name = strdup(args[1]);
3646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003650
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003651 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 /* enable reconnections to dispatch */
3655 curproxy->options |= PR_O_REDISP;
3656 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003657 else if (!strcmp(args[0], "http-check")) {
3658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003660
3661 if (strcmp(args[1], "disable-on-404") == 0) {
3662 /* enable a graceful server shutdown on an HTTP 404 response */
3663 curproxy->options |= PR_O_DISABLE404;
3664 }
Willy Tarreauef781042010-01-27 11:53:01 +01003665 else if (strcmp(args[1], "send-state") == 0) {
3666 /* enable emission of the apparent state of a server in HTTP checks */
3667 curproxy->options2 |= PR_O2_CHK_SNDST;
3668 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003669 else if (strcmp(args[1], "expect") == 0) {
3670 const char *ptr_arg;
3671 int cur_arg;
3672
3673 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3674 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
3677 }
3678
3679 cur_arg = 2;
3680 /* consider exclamation marks, sole or at the beginning of a word */
3681 while (*(ptr_arg = args[cur_arg])) {
3682 while (*ptr_arg == '!') {
3683 curproxy->options2 ^= PR_O2_EXP_INV;
3684 ptr_arg++;
3685 }
3686 if (*ptr_arg)
3687 break;
3688 cur_arg++;
3689 }
3690 /* now ptr_arg points to the beginning of a word past any possible
3691 * exclamation mark, and cur_arg is the argument which holds this word.
3692 */
3693 if (strcmp(ptr_arg, "status") == 0) {
3694 if (!*(args[cur_arg + 1])) {
3695 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3696 file, linenum, args[0], args[1], ptr_arg);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700 curproxy->options2 |= PR_O2_EXP_STS;
3701 curproxy->expect_str = strdup(args[cur_arg + 1]);
3702 }
3703 else if (strcmp(ptr_arg, "string") == 0) {
3704 if (!*(args[cur_arg + 1])) {
3705 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3706 file, linenum, args[0], args[1], ptr_arg);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710 curproxy->options2 |= PR_O2_EXP_STR;
3711 curproxy->expect_str = strdup(args[cur_arg + 1]);
3712 }
3713 else if (strcmp(ptr_arg, "rstatus") == 0) {
3714 if (!*(args[cur_arg + 1])) {
3715 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3716 file, linenum, args[0], args[1], ptr_arg);
3717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
3719 }
3720 curproxy->options2 |= PR_O2_EXP_RSTS;
3721 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3722 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3723 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3724 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
3728 }
3729 else if (strcmp(ptr_arg, "rstring") == 0) {
3730 if (!*(args[cur_arg + 1])) {
3731 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3732 file, linenum, args[0], args[1], ptr_arg);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736 curproxy->options2 |= PR_O2_EXP_RSTR;
3737 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3738 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3739 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3740 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
3743 }
3744 }
3745 else {
3746 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3747 file, linenum, args[0], args[1], ptr_arg);
3748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
3750 }
3751 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003752 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003753 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003756 }
3757 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003758 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003759 if (curproxy == &defproxy) {
3760 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003763 }
3764
Willy Tarreaub80c2302007-11-30 20:51:32 +01003765 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003767
3768 if (strcmp(args[1], "fail") == 0) {
3769 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003770 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003771 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3772 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003775 }
3776
Willy Tarreauef6494c2010-01-28 17:12:36 +01003777 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003778 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3779 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003782 }
3783 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3784 }
3785 else {
3786 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003789 }
3790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791#ifdef TPROXY
3792 else if (!strcmp(args[0], "transparent")) {
3793 /* enable transparent proxy connections */
3794 curproxy->options |= PR_O_TRANSP;
3795 }
3796#endif
3797 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003800
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 if (*(args[1]) == 0) {
3802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
3806 curproxy->maxconn = atol(args[1]);
3807 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003808 else if (!strcmp(args[0], "backlog")) { /* backlog */
3809 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003811
3812 if (*(args[1]) == 0) {
3813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003816 }
3817 curproxy->backlog = atol(args[1]);
3818 }
Willy Tarreau86034312006-12-29 00:10:33 +01003819 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003822
Willy Tarreau86034312006-12-29 00:10:33 +01003823 if (*(args[1]) == 0) {
3824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003827 }
3828 curproxy->fullconn = atol(args[1]);
3829 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3831 if (*(args[1]) == 0) {
3832 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003836 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3837 if (err) {
3838 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3839 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003842 }
3843 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
3845 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003846 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 if (curproxy == &defproxy) {
3848 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003852 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003854
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 if (strchr(args[1], ':') == NULL) {
3856 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003860 sk = str2sa(args[1]);
3861 if (!sk) {
3862 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003867 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003870 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003872
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003873 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003874 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3875 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003880 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3882 err_code |= ERR_WARN;
3883
3884 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3885 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3886 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3887 }
3888 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3889 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3890 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3891 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003892 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3893 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3894 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3895 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003896 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003897 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
3900 }
3901 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003902 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003904 char *rport, *raddr;
3905 short realport = 0;
3906 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003908 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003913 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915
3916 if (!*args[2]) {
3917 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3918 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003922
3923 err = invalid_char(args[1]);
3924 if (err) {
3925 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3926 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003929 }
3930
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003931 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003932 struct sockaddr_in *sk;
3933
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003934 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3935 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3936 err_code |= ERR_ALERT | ERR_ABORT;
3937 goto out;
3938 }
3939
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003940 /* the servers are linked backwards first */
3941 newsrv->next = curproxy->srv;
3942 curproxy->srv = newsrv;
3943 newsrv->proxy = curproxy;
3944 newsrv->conf.file = file;
3945 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003947 LIST_INIT(&newsrv->pendconns);
3948 do_check = 0;
3949 newsrv->state = SRV_RUNNING; /* early server setup */
3950 newsrv->last_change = now.tv_sec;
3951 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003953 /* several ways to check the port component :
3954 * - IP => port=+0, relative
3955 * - IP: => port=+0, relative
3956 * - IP:N => port=N, absolute
3957 * - IP:+N => port=+N, relative
3958 * - IP:-N => port=-N, relative
3959 */
3960 raddr = strdup(args[2]);
3961 rport = strchr(raddr, ':');
3962 if (rport) {
3963 *rport++ = 0;
3964 realport = atol(rport);
3965 if (!isdigit((unsigned char)*rport))
3966 newsrv->state |= SRV_MAPPORTS;
3967 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003969
Willy Tarreaud5191e72010-02-09 20:50:45 +01003970 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003971 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003972 if (!sk) {
3973 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
3976 }
3977 newsrv->addr = *sk;
3978 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003979
3980 newsrv->check_port = curproxy->defsrv.check_port;
3981 newsrv->inter = curproxy->defsrv.inter;
3982 newsrv->fastinter = curproxy->defsrv.fastinter;
3983 newsrv->downinter = curproxy->defsrv.downinter;
3984 newsrv->rise = curproxy->defsrv.rise;
3985 newsrv->fall = curproxy->defsrv.fall;
3986 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3987 newsrv->minconn = curproxy->defsrv.minconn;
3988 newsrv->maxconn = curproxy->defsrv.maxconn;
3989 newsrv->slowstart = curproxy->defsrv.slowstart;
3990 newsrv->onerror = curproxy->defsrv.onerror;
3991 newsrv->consecutive_errors_limit
3992 = curproxy->defsrv.consecutive_errors_limit;
3993 newsrv->uweight = newsrv->iweight
3994 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003996 newsrv->curfd = -1; /* no health-check in progress */
3997 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003999 cur_arg = 3;
4000 } else {
4001 newsrv = &curproxy->defsrv;
4002 cur_arg = 1;
4003 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004004
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004006 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004007 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004008
4009 if (!*args[cur_arg + 1]) {
4010 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4011 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004014 }
4015
4016 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004017 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004018
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004019 if (newsrv->puid <= 0) {
4020 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004021 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004024 }
4025
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004026 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4027 if (node) {
4028 struct server *target = container_of(node, struct server, conf.id);
4029 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4030 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
4033 }
4034 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004035 cur_arg += 2;
4036 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004037 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 newsrv->cookie = strdup(args[cur_arg + 1]);
4039 newsrv->cklen = strlen(args[cur_arg + 1]);
4040 cur_arg += 2;
4041 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004042 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004043 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4044 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4045 cur_arg += 2;
4046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004048 if (!*args[cur_arg + 1]) {
4049 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4050 file, linenum, args[cur_arg]);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004056 if (newsrv->rise <= 0) {
4057 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4058 file, linenum, args[cur_arg]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062
Willy Tarreau96839092010-03-29 10:02:24 +02004063 if (newsrv->health)
4064 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 cur_arg += 2;
4066 }
4067 else if (!strcmp(args[cur_arg], "fall")) {
4068 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004069
4070 if (!*args[cur_arg + 1]) {
4071 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4072 file, linenum, args[cur_arg]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076
4077 if (newsrv->fall <= 0) {
4078 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4079 file, linenum, args[cur_arg]);
4080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
4082 }
4083
Willy Tarreaubaaee002006-06-26 02:48:02 +02004084 cur_arg += 2;
4085 }
4086 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004087 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4088 if (err) {
4089 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4090 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004093 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004094 if (val <= 0) {
4095 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4096 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004099 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004100 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101 cur_arg += 2;
4102 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004103 else if (!strcmp(args[cur_arg], "fastinter")) {
4104 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4105 if (err) {
4106 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4107 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004110 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004111 if (val <= 0) {
4112 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4113 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004116 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004117 newsrv->fastinter = val;
4118 cur_arg += 2;
4119 }
4120 else if (!strcmp(args[cur_arg], "downinter")) {
4121 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4122 if (err) {
4123 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4124 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004127 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004128 if (val <= 0) {
4129 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4130 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004133 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004134 newsrv->downinter = val;
4135 cur_arg += 2;
4136 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004137 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004138 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4139 if (!sk) {
4140 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
4143 }
4144 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004145 cur_arg += 2;
4146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147 else if (!strcmp(args[cur_arg], "port")) {
4148 newsrv->check_port = atol(args[cur_arg + 1]);
4149 cur_arg += 2;
4150 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004151 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 newsrv->state |= SRV_BACKUP;
4153 cur_arg ++;
4154 }
4155 else if (!strcmp(args[cur_arg], "weight")) {
4156 int w;
4157 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004158 if (w < 0 || w > 256) {
4159 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004164 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 cur_arg += 2;
4166 }
4167 else if (!strcmp(args[cur_arg], "minconn")) {
4168 newsrv->minconn = atol(args[cur_arg + 1]);
4169 cur_arg += 2;
4170 }
4171 else if (!strcmp(args[cur_arg], "maxconn")) {
4172 newsrv->maxconn = atol(args[cur_arg + 1]);
4173 cur_arg += 2;
4174 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004175 else if (!strcmp(args[cur_arg], "maxqueue")) {
4176 newsrv->maxqueue = atol(args[cur_arg + 1]);
4177 cur_arg += 2;
4178 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004179 else if (!strcmp(args[cur_arg], "slowstart")) {
4180 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004181 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004182 if (err) {
4183 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4184 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004187 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004188 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004189 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4190 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004193 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004194 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004195 cur_arg += 2;
4196 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004197 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004198
4199 if (!*args[cur_arg + 1]) {
4200 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4201 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004204 }
4205
4206 newsrv->trackit = strdup(args[cur_arg + 1]);
4207
4208 cur_arg += 2;
4209 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 global.maxsock++;
4212 do_check = 1;
4213 cur_arg += 1;
4214 }
Willy Tarreau96839092010-03-29 10:02:24 +02004215 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4216 newsrv->state |= SRV_MAINTAIN;
4217 newsrv->state &= ~SRV_RUNNING;
4218 newsrv->health = 0;
4219 cur_arg += 1;
4220 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004221 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004222 if (!strcmp(args[cur_arg + 1], "none"))
4223 newsrv->observe = HANA_OBS_NONE;
4224 else if (!strcmp(args[cur_arg + 1], "layer4"))
4225 newsrv->observe = HANA_OBS_LAYER4;
4226 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4227 if (curproxy->mode != PR_MODE_HTTP) {
4228 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4229 file, linenum, args[cur_arg + 1]);
4230 err_code |= ERR_ALERT;
4231 }
4232 newsrv->observe = HANA_OBS_LAYER7;
4233 }
4234 else {
4235 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004236 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004237 file, linenum, args[cur_arg], args[cur_arg + 1]);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
4240 }
4241
4242 cur_arg += 2;
4243 }
4244 else if (!strcmp(args[cur_arg], "on-error")) {
4245 if (!strcmp(args[cur_arg + 1], "fastinter"))
4246 newsrv->onerror = HANA_ONERR_FASTINTER;
4247 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4248 newsrv->onerror = HANA_ONERR_FAILCHK;
4249 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4250 newsrv->onerror = HANA_ONERR_SUDDTH;
4251 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4252 newsrv->onerror = HANA_ONERR_MARKDWN;
4253 else {
4254 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004255 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004256 file, linenum, args[cur_arg], args[cur_arg + 1]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
4261 cur_arg += 2;
4262 }
4263 else if (!strcmp(args[cur_arg], "error-limit")) {
4264 if (!*args[cur_arg + 1]) {
4265 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4266 file, linenum, args[cur_arg]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270
4271 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4272
4273 if (newsrv->consecutive_errors_limit <= 0) {
4274 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4275 file, linenum, args[cur_arg]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004279 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004280 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004281 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004282 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004283 struct sockaddr_in *sk;
4284
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004286#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004287 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004288 file, linenum, "source", "usesrc");
4289#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004290 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004291 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004292#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 }
4296 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004297 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4298 if (!sk) {
4299 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
4302 }
4303 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004304
4305 if (port_low != port_high) {
4306 int i;
4307 if (port_low <= 0 || port_low > 65535 ||
4308 port_high <= 0 || port_high > 65535 ||
4309 port_low > port_high) {
4310 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4311 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004314 }
4315 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4316 for (i = 0; i < newsrv->sport_range->size; i++)
4317 newsrv->sport_range->ports[i] = port_low + i;
4318 }
4319
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004321 while (*(args[cur_arg])) {
4322 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004323#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4324#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4326 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4327 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004330 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004331#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004332 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004333 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004334 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004337 }
4338 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004339 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004340 newsrv->state |= SRV_TPROXY_CLI;
4341 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004342 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004343 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004344 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4345 char *name, *end;
4346
4347 name = args[cur_arg+1] + 7;
4348 while (isspace(*name))
4349 name++;
4350
4351 end = name;
4352 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4353 end++;
4354
4355 newsrv->state &= ~SRV_TPROXY_MASK;
4356 newsrv->state |= SRV_TPROXY_DYN;
4357 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4358 newsrv->bind_hdr_len = end - name;
4359 memcpy(newsrv->bind_hdr_name, name, end - name);
4360 newsrv->bind_hdr_name[end-name] = '\0';
4361 newsrv->bind_hdr_occ = -1;
4362
4363 /* now look for an occurrence number */
4364 while (isspace(*end))
4365 end++;
4366 if (*end == ',') {
4367 end++;
4368 name = end;
4369 if (*end == '-')
4370 end++;
4371 while (isdigit(*end))
4372 end++;
4373 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4374 }
4375
4376 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4377 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4378 " occurrences values smaller than %d.\n",
4379 file, linenum, MAX_HDR_HISTORY);
4380 err_code |= ERR_ALERT | ERR_FATAL;
4381 goto out;
4382 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004384 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4385 if (!sk) {
4386 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
4389 }
4390 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004391 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004392 }
4393 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004394#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004396#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004397 cur_arg += 2;
4398 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004399#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004400 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004401 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004404#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4405 } /* "usesrc" */
4406
4407 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4408#ifdef SO_BINDTODEVICE
4409 if (!*args[cur_arg + 1]) {
4410 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4411 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004414 }
4415 if (newsrv->iface_name)
4416 free(newsrv->iface_name);
4417
4418 newsrv->iface_name = strdup(args[cur_arg + 1]);
4419 newsrv->iface_len = strlen(newsrv->iface_name);
4420 global.last_checks |= LSTCHK_NETADM;
4421#else
4422 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4423 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004426#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004427 cur_arg += 2;
4428 continue;
4429 }
4430 /* this keyword in not an option of "source" */
4431 break;
4432 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004434 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004435 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4436 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004441 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004442 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 +01004443 file, linenum, newsrv->id);
4444 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004445 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 +01004446 file, linenum);
4447
Willy Tarreau93893792009-07-23 13:19:11 +02004448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 }
4451 }
4452
4453 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004454 if (newsrv->trackit) {
4455 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4456 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004459 }
4460
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004461 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4462 newsrv->check_port = newsrv->check_addr.sin_port;
4463
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4465 newsrv->check_port = realport; /* by default */
4466 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004467 /* not yet valid, because no port was set on
4468 * the server either. We'll check if we have
4469 * a known port on the first listener.
4470 */
4471 struct listener *l;
4472 l = curproxy->listen;
4473 if (l) {
4474 int port;
4475 port = (l->addr.ss_family == AF_INET6)
4476 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4477 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4478 newsrv->check_port = port;
4479 }
4480 }
4481 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4483 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004487
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004488 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004489 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004490 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4491 err_code |= ERR_ALERT | ERR_ABORT;
4492 goto out;
4493 }
4494
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004495 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 newsrv->state |= SRV_CHECKED;
4497 }
4498
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004499 if (!defsrv) {
4500 if (newsrv->state & SRV_BACKUP)
4501 curproxy->srv_bck++;
4502 else
4503 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004504
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004505 newsrv->prev_state = newsrv->state;
4506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 }
4508 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004509 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 int facility;
4511
4512 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4513 curproxy->logfac1 = global.logfac1;
4514 curproxy->logsrv1 = global.logsrv1;
4515 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004516 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 curproxy->logfac2 = global.logfac2;
4518 curproxy->logsrv2 = global.logsrv2;
4519 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004520 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 }
4522 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004523 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524
4525 facility = get_log_facility(args[2]);
4526 if (facility < 0) {
4527 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4528 exit(1);
4529 }
4530
4531 level = 7; /* max syslog level = debug */
4532 if (*(args[3])) {
4533 level = get_log_level(args[3]);
4534 if (level < 0) {
4535 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4536 exit(1);
4537 }
4538 }
4539
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004540 minlvl = 0; /* limit syslog level to this level (emerg) */
4541 if (*(args[4])) {
4542 minlvl = get_log_level(args[4]);
4543 if (level < 0) {
4544 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4545 exit(1);
4546 }
4547 }
4548
Robert Tsai81ae1952007-12-05 10:47:29 +01004549 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004550 struct sockaddr_un *sk = str2sun(args[1]);
4551 if (!sk) {
4552 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4553 args[1], (int)sizeof(sk->sun_path) - 1);
4554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
4556 }
4557 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004558 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004559 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004560 struct sockaddr_in *sk = str2sa(args[1]);
4561 if (!sk) {
4562 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4563 err_code |= ERR_ALERT | ERR_FATAL;
4564 goto out;
4565 }
4566 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004567 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004568 if (!logsrv.u.in.sin_port) {
4569 logsrv.u.in.sin_port =
4570 htons(SYSLOG_PORT);
4571 }
4572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573
4574 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004575 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 curproxy->logfac1 = facility;
4577 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004578 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 }
4580 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004581 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 curproxy->logfac2 = facility;
4583 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004584 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004585 }
4586 else {
4587 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
4591 }
4592 else {
4593 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4594 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 }
4598 }
4599 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004600 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004601 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004602
Willy Tarreau977b8e42006-12-29 14:19:17 +01004603 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004605
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004607 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4608 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_ALERT | ERR_FATAL;
4610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004612
4613 /* we must first clear any optional default setting */
4614 curproxy->options &= ~PR_O_TPXY_MASK;
4615 free(curproxy->iface_name);
4616 curproxy->iface_name = NULL;
4617 curproxy->iface_len = 0;
4618
Willy Tarreaud5191e72010-02-09 20:50:45 +01004619 sk = str2sa(args[1]);
4620 if (!sk) {
4621 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004627
4628 cur_arg = 2;
4629 while (*(args[cur_arg])) {
4630 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004631#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4632#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004633 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4634 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4635 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004638 }
4639#endif
4640 if (!*args[cur_arg + 1]) {
4641 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4642 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004645 }
4646
4647 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004648 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004649 curproxy->options |= PR_O_TPXY_CLI;
4650 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004651 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004652 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004653 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4654 char *name, *end;
4655
4656 name = args[cur_arg+1] + 7;
4657 while (isspace(*name))
4658 name++;
4659
4660 end = name;
4661 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4662 end++;
4663
4664 curproxy->options &= ~PR_O_TPXY_MASK;
4665 curproxy->options |= PR_O_TPXY_DYN;
4666 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4667 curproxy->bind_hdr_len = end - name;
4668 memcpy(curproxy->bind_hdr_name, name, end - name);
4669 curproxy->bind_hdr_name[end-name] = '\0';
4670 curproxy->bind_hdr_occ = -1;
4671
4672 /* now look for an occurrence number */
4673 while (isspace(*end))
4674 end++;
4675 if (*end == ',') {
4676 end++;
4677 name = end;
4678 if (*end == '-')
4679 end++;
4680 while (isdigit(*end))
4681 end++;
4682 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4683 }
4684
4685 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4686 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4687 " occurrences values smaller than %d.\n",
4688 file, linenum, MAX_HDR_HISTORY);
4689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004692 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004693 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4694 if (!sk) {
4695 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
4698 }
4699 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004701 }
4702 global.last_checks |= LSTCHK_NETADM;
4703#if !defined(CONFIG_HAP_LINUX_TPROXY)
4704 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004705#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004706#else /* no TPROXY support */
4707 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004708 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004711#endif
4712 cur_arg += 2;
4713 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004714 }
4715
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004716 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4717#ifdef SO_BINDTODEVICE
4718 if (!*args[cur_arg + 1]) {
4719 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4720 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004723 }
4724 if (curproxy->iface_name)
4725 free(curproxy->iface_name);
4726
4727 curproxy->iface_name = strdup(args[cur_arg + 1]);
4728 curproxy->iface_len = strlen(curproxy->iface_name);
4729 global.last_checks |= LSTCHK_NETADM;
4730#else
4731 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4732 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004735#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004736 cur_arg += 2;
4737 continue;
4738 }
4739 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4740 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004745 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4746 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4747 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4754 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004758
4759 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4760 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004761 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004762 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
4765 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4767 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004768 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
4772 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4774 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
4779 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4781 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004785 }
4786 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4788 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004789 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004793 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4795 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004796 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004798 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004799 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004800 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4802 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004803 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004805 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004806 }
4807 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4809 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004810 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004812 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004816 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4817 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004821
4822 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4823 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004824 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 }
4828 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004829 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4830 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004831 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 }
4835 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4837 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004838 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004839 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 }
4842 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004843 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4844 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004845 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004846 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 }
4849 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004850 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4851 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004852 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004853 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004856 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004857 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4858 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004859 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004860 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004861 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004864 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004865
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 if (curproxy == &defproxy) {
4867 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004871 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004872 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 if (*(args[1]) == 0) {
4875 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004879
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004880 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4881 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4882 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4883 file, linenum, args[0]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4888 }
4889 else if (*args[2]) {
4890 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4891 file, linenum, args[0], args[2]);
4892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
4894 }
4895
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004896 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004897 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004898 wl->s = strdup(args[1]);
4899 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004900 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
4902 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004903 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4905 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004906 err_code |= ERR_ALERT | ERR_FATAL;
4907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004909
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4911 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004912 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004913 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
4916 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4918 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004919 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004920 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 }
4923 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4925 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004926 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
4930 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
4937
Willy Tarreauade5ec42010-01-28 19:33:49 +01004938 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4939 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004940 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
4944 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4946 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004947 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
4951 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4953 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004954 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004955 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
4958 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004959 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 if (curproxy == &defproxy) {
4962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004966 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 if (*(args[1]) == 0) {
4970 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
4974
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004975 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4976 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4977 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4978 file, linenum, args[0]);
4979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
4981 }
4982 err_code |= warnif_cond_requires_req(cond, file, linenum);
4983 }
4984 else if (*args[2]) {
4985 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4986 file, linenum, args[0], args[2]);
4987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
4989 }
4990
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004991 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004992 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004993 wl->s = strdup(args[1]);
4994 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
4996 else if (!strcmp(args[0], "errorloc") ||
4997 !strcmp(args[0], "errorloc302") ||
4998 !strcmp(args[0], "errorloc303")) { /* error location */
4999 int errnum, errlen;
5000 char *err;
5001
Willy Tarreau977b8e42006-12-29 14:19:17 +01005002 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005004
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005006 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 }
5010
5011 errnum = atol(args[1]);
5012 if (!strcmp(args[0], "errorloc303")) {
5013 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5014 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5015 } else {
5016 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5017 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5018 }
5019
Willy Tarreau0f772532006-12-23 20:51:41 +01005020 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5021 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005022 chunk_destroy(&curproxy->errmsg[rc]);
5023 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005024 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005027
5028 if (rc >= HTTP_ERR_SIZE) {
5029 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5030 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 free(err);
5032 }
5033 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005034 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5035 int errnum, errlen, fd;
5036 char *err;
5037 struct stat stat;
5038
5039 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005041
5042 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005043 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005046 }
5047
5048 fd = open(args[2], O_RDONLY);
5049 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5050 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5051 file, linenum, args[2], args[1]);
5052 if (fd >= 0)
5053 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005056 }
5057
Willy Tarreau27a674e2009-08-17 07:23:33 +02005058 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005059 errlen = stat.st_size;
5060 } else {
5061 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005062 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005064 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005065 }
5066
5067 err = malloc(errlen); /* malloc() must succeed during parsing */
5068 errnum = read(fd, err, errlen);
5069 if (errnum != errlen) {
5070 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5071 file, linenum, args[2], args[1]);
5072 close(fd);
5073 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005076 }
5077 close(fd);
5078
5079 errnum = atol(args[1]);
5080 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5081 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005082 chunk_destroy(&curproxy->errmsg[rc]);
5083 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005084 break;
5085 }
5086 }
5087
5088 if (rc >= HTTP_ERR_SIZE) {
5089 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5090 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005092 free(err);
5093 }
5094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005096 struct cfg_kw_list *kwl;
5097 int index;
5098
5099 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5100 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5101 if (kwl->kw[index].section != CFG_LISTEN)
5102 continue;
5103 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5104 /* prepare error message just in case */
5105 snprintf(trash, sizeof(trash),
5106 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005107 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5108 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005109 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005112 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005113 else if (rc > 0) {
5114 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_WARN;
5116 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005117 }
Willy Tarreau93893792009-07-23 13:19:11 +02005118 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005119 }
5120 }
5121 }
5122
Willy Tarreau6daf3432008-01-22 16:44:08 +01005123 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
Willy Tarreau93893792009-07-23 13:19:11 +02005127 out:
5128 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129}
5130
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005131int
5132cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5133{
5134
5135 int err_code = 0;
5136 const char *err;
5137
5138 if (!strcmp(args[0], "userlist")) { /* new userlist */
5139 struct userlist *newul;
5140
5141 if (!*args[1]) {
5142 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5143 file, linenum, args[0]);
5144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
5146 }
5147
5148 err = invalid_char(args[1]);
5149 if (err) {
5150 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5151 file, linenum, *err, args[0], args[1]);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
5155
5156 for (newul = userlist; newul; newul = newul->next)
5157 if (!strcmp(newul->name, args[1])) {
5158 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5159 file, linenum, args[1]);
5160 err_code |= ERR_WARN;
5161 goto out;
5162 }
5163
5164 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5165 if (!newul) {
5166 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5167 err_code |= ERR_ALERT | ERR_ABORT;
5168 goto out;
5169 }
5170
5171 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5172 newul->name = strdup(args[1]);
5173
5174 if (!newul->groupusers | !newul->name) {
5175 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5176 err_code |= ERR_ALERT | ERR_ABORT;
5177 goto out;
5178 }
5179
5180 newul->next = userlist;
5181 userlist = newul;
5182
5183 } else if (!strcmp(args[0], "group")) { /* new group */
5184 int cur_arg, i;
5185 const char *err;
5186
5187 if (!*args[1]) {
5188 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5189 file, linenum, args[0]);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193
5194 err = invalid_char(args[1]);
5195 if (err) {
5196 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5197 file, linenum, *err, args[0], args[1]);
5198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
5200 }
5201
5202 for(i = 0; i < userlist->grpcnt; i++)
5203 if (!strcmp(userlist->groups[i], args[1])) {
5204 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5205 file, linenum, args[1], userlist->name);
5206 err_code |= ERR_ALERT;
5207 goto out;
5208 }
5209
5210 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5211 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5212 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
5216
5217 cur_arg = 2;
5218
5219 while (*args[cur_arg]) {
5220 if (!strcmp(args[cur_arg], "users")) {
5221 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5222 cur_arg += 2;
5223 continue;
5224 } else {
5225 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5226 file, linenum, args[0]);
5227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229 }
5230 }
5231
5232 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5233 } else if (!strcmp(args[0], "user")) { /* new user */
5234 struct auth_users *newuser;
5235 int cur_arg;
5236
5237 if (!*args[1]) {
5238 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5239 file, linenum, args[0]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243
5244 for (newuser = userlist->users; newuser; newuser = newuser->next)
5245 if (!strcmp(newuser->user, args[1])) {
5246 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5247 file, linenum, args[1], userlist->name);
5248 err_code |= ERR_ALERT;
5249 goto out;
5250 }
5251
5252 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5253 if (!newuser) {
5254 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5255 err_code |= ERR_ALERT | ERR_ABORT;
5256 goto out;
5257 }
5258
5259 newuser->user = strdup(args[1]);
5260
5261 newuser->next = userlist->users;
5262 userlist->users = newuser;
5263
5264 cur_arg = 2;
5265
5266 while (*args[cur_arg]) {
5267 if (!strcmp(args[cur_arg], "password")) {
5268#ifndef CONFIG_HAP_CRYPT
5269 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5270 file, linenum);
5271 err_code |= ERR_ALERT;
5272#endif
5273 newuser->pass = strdup(args[cur_arg + 1]);
5274 cur_arg += 2;
5275 continue;
5276 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5277 newuser->pass = strdup(args[cur_arg + 1]);
5278 newuser->flags |= AU_O_INSECURE;
5279 cur_arg += 2;
5280 continue;
5281 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005282 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005283 cur_arg += 2;
5284 continue;
5285 } else {
5286 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5287 file, linenum, args[0]);
5288 err_code |= ERR_ALERT | ERR_FATAL;
5289 goto out;
5290 }
5291 }
5292 } else {
5293 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 }
5296
5297out:
5298 return err_code;
5299}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300
5301/*
5302 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005303 * Returns the error code, 0 if OK, or any combination of :
5304 * - ERR_ABORT: must abort ASAP
5305 * - ERR_FATAL: we can continue parsing but not start the service
5306 * - ERR_WARN: a warning has been emitted
5307 * - ERR_ALERT: an alert has been emitted
5308 * Only the two first ones can stop processing, the two others are just
5309 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005311int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005313 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 FILE *f;
5315 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005317 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 if ((f=fopen(file,"r")) == NULL)
5320 return -1;
5321
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005322 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005323 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005324 char *end;
5325 char *args[MAX_LINE_ARGS + 1];
5326 char *line = thisline;
5327
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 linenum++;
5329
5330 end = line + strlen(line);
5331
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005332 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5333 /* Check if we reached the limit and the last char is not \n.
5334 * Watch out for the last line without the terminating '\n'!
5335 */
5336 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005337 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005338 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005339 }
5340
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005342 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 line++;
5344
5345 arg = 0;
5346 args[arg] = line;
5347
5348 while (*line && arg < MAX_LINE_ARGS) {
5349 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5350 * C equivalent value. Other combinations left unchanged (eg: \1).
5351 */
5352 if (*line == '\\') {
5353 int skip = 0;
5354 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5355 *line = line[1];
5356 skip = 1;
5357 }
5358 else if (line[1] == 'r') {
5359 *line = '\r';
5360 skip = 1;
5361 }
5362 else if (line[1] == 'n') {
5363 *line = '\n';
5364 skip = 1;
5365 }
5366 else if (line[1] == 't') {
5367 *line = '\t';
5368 skip = 1;
5369 }
5370 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005371 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 unsigned char hex1, hex2;
5373 hex1 = toupper(line[2]) - '0';
5374 hex2 = toupper(line[3]) - '0';
5375 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5376 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5377 *line = (hex1<<4) + hex2;
5378 skip = 3;
5379 }
5380 else {
5381 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
5384 }
5385 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005386 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 end -= skip;
5388 }
5389 line++;
5390 }
5391 else if (*line == '#' || *line == '\n' || *line == '\r') {
5392 /* end of string, end of loop */
5393 *line = 0;
5394 break;
5395 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005396 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005398 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005399 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 line++;
5401 args[++arg] = line;
5402 }
5403 else {
5404 line++;
5405 }
5406 }
5407
5408 /* empty line */
5409 if (!**args)
5410 continue;
5411
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005412 if (*line) {
5413 /* we had to stop due to too many args.
5414 * Let's terminate the string, print the offending part then cut the
5415 * last arg.
5416 */
5417 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5418 line++;
5419 *line = '\0';
5420
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005421 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005422 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005423 err_code |= ERR_ALERT | ERR_FATAL;
5424 args[arg] = line;
5425 }
5426
Willy Tarreau540abe42007-05-02 20:50:16 +02005427 /* zero out remaining args and ensure that at least one entry
5428 * is zeroed out.
5429 */
5430 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 args[arg] = line;
5432 }
5433
Willy Tarreau3842f002009-06-14 11:39:52 +02005434 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005435 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005436 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005437 for (arg=0; *args[arg+1]; arg++)
5438 args[arg] = args[arg+1]; // shift args after inversion
5439 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005440 else if (!strcmp(args[0], "default")) {
5441 kwm = KWM_DEF;
5442 for (arg=0; *args[arg+1]; arg++)
5443 args[arg] = args[arg+1]; // shift args after inversion
5444 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005445
Willy Tarreau3842f002009-06-14 11:39:52 +02005446 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5447 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005448 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005449 }
5450
Willy Tarreau977b8e42006-12-29 14:19:17 +01005451 if (!strcmp(args[0], "listen") ||
5452 !strcmp(args[0], "frontend") ||
5453 !strcmp(args[0], "backend") ||
5454 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005455 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005456 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005457 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005458 cursection = strdup(args[0]);
5459 }
5460 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005462 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005463 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005464 }
5465 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005466 confsect = CFG_USERLIST;
5467 free(cursection);
5468 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005469 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005470 else if (!strcmp(args[0], "peers")) {
5471 confsect = CFG_PEERS;
5472 free(cursection);
5473 cursection = strdup(args[0]);
5474 }
5475
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 /* else it's a section keyword */
5477
5478 switch (confsect) {
5479 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005480 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 break;
5482 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005483 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005485 case CFG_USERLIST:
5486 err_code |= cfg_parse_users(file, linenum, args, kwm);
5487 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005488 case CFG_PEERS:
5489 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5490 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005492 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005493 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005495
5496 if (err_code & ERR_ABORT)
5497 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005498 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005499 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005500 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005502 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005503}
5504
Willy Tarreaubb925012009-07-23 13:36:36 +02005505/*
5506 * Returns the error code, 0 if OK, or any combination of :
5507 * - ERR_ABORT: must abort ASAP
5508 * - ERR_FATAL: we can continue parsing but not start the service
5509 * - ERR_WARN: a warning has been emitted
5510 * - ERR_ALERT: an alert has been emitted
5511 * Only the two first ones can stop processing, the two others are just
5512 * indicators.
5513 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005514int check_config_validity()
5515{
5516 int cfgerr = 0;
5517 struct proxy *curproxy = NULL;
5518 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005519 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005520 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005521 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522
5523 /*
5524 * Now, check for the integrity of all that we have collected.
5525 */
5526
5527 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005528 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005530 /* first, we will invert the proxy list order */
5531 curproxy = NULL;
5532 while (proxy) {
5533 struct proxy *next;
5534
5535 next = proxy->next;
5536 proxy->next = curproxy;
5537 curproxy = proxy;
5538 if (!next)
5539 break;
5540 proxy = next;
5541 }
5542
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005544 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005547 }
5548
5549 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005550 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005551 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005552 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005553 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005554 unsigned int next_id;
5555
5556 if (!curproxy->uuid) {
5557 /* proxy ID not set, use automatic numbering with first
5558 * spare entry starting with next_pxid.
5559 */
5560 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5561 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5562 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005563 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005564 next_pxid++;
5565
Willy Tarreau55ea7572007-06-17 19:56:27 +02005566
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005568 /* ensure we don't keep listeners uselessly bound */
5569 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 curproxy = curproxy->next;
5571 continue;
5572 }
5573
Willy Tarreauff01a212009-03-15 13:46:16 +01005574 switch (curproxy->mode) {
5575 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005576 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005577 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005578 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5579 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005580 cfgerr++;
5581 }
5582
5583 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005584 Warning("config : servers will be ignored for %s '%s'.\n",
5585 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005586 break;
5587
5588 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005589 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005590 break;
5591
5592 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005593 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005594 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005595 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5596 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005597 cfgerr++;
5598 }
5599 break;
5600 }
5601
5602 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005603 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5604 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 cfgerr++;
5606 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005607
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005608 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005609 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005610 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005611 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5612 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005613 cfgerr++;
5614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005616 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005617 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5618 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005619 cfgerr++;
5620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005622 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005623 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5624 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005625 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005626 }
5627 }
5628 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005629 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005630 /* If no LB algo is set in a backend, and we're not in
5631 * transparent mode, dispatch mode nor proxy mode, we
5632 * want to use balance roundrobin by default.
5633 */
5634 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5635 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 }
5637 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005638
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005639 if (curproxy->options2 & PR_O2_DISPATCH) {
5640 curproxy->options &= ~PR_O_TRANSP;
5641 curproxy->options &= ~PR_O_HTTP_PROXY;
5642 }
5643 else if (curproxy->options & PR_O_HTTP_PROXY) {
5644 curproxy->options2 &= ~PR_O2_DISPATCH;
5645 curproxy->options &= ~PR_O_TRANSP;
5646 }
5647 else if (curproxy->options & PR_O_TRANSP) {
5648 curproxy->options2 &= ~PR_O2_DISPATCH;
5649 curproxy->options &= ~PR_O_HTTP_PROXY;
5650 }
5651
Willy Tarreau82936582007-11-30 15:20:09 +01005652 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5653 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005654 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5655 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005656 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005657 }
5658
Willy Tarreauef781042010-01-27 11:53:01 +01005659 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5660 curproxy->options &= ~PR_O2_CHK_SNDST;
5661 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5662 "send-state", proxy_type_str(curproxy), curproxy->id);
5663 err_code |= ERR_WARN;
5664 }
5665
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005666 /* if a default backend was specified, let's find it */
5667 if (curproxy->defbe.name) {
5668 struct proxy *target;
5669
Alex Williams96532db2009-11-01 21:27:13 -05005670 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005671 if (!target) {
5672 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5673 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005674 cfgerr++;
5675 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005676 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5677 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005678 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005679 } else {
5680 free(curproxy->defbe.name);
5681 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005682 /* we force the backend to be present on at least all of
5683 * the frontend's processes.
5684 */
5685 target->bind_proc = curproxy->bind_proc ?
5686 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 }
5688 }
5689
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005690 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005691 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5692 /* map jump target for ACT_SETBE in req_rep chain */
5693 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005694 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005695 struct proxy *target;
5696
Willy Tarreaua496b602006-12-17 23:15:24 +01005697 if (exp->action != ACT_SETBE)
5698 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005699
Alex Williams96532db2009-11-01 21:27:13 -05005700 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005701 if (!target) {
5702 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5703 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005704 cfgerr++;
5705 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005706 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5707 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005708 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005709 } else {
5710 free((void *)exp->replace);
5711 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005712 /* we force the backend to be present on at least all of
5713 * the frontend's processes.
5714 */
5715 target->bind_proc = curproxy->bind_proc ?
5716 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005717 }
5718 }
5719 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005720
5721 /* find the target proxy for 'use_backend' rules */
5722 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005723 struct proxy *target;
5724
Alex Williams96532db2009-11-01 21:27:13 -05005725 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005726
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005727 if (!target) {
5728 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5729 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005730 cfgerr++;
5731 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005732 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5733 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005734 cfgerr++;
5735 } else {
5736 free((void *)rule->be.name);
5737 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005738 /* we force the backend to be present on at least all of
5739 * the frontend's processes.
5740 */
5741 target->bind_proc = curproxy->bind_proc ?
5742 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005743 }
5744 }
5745
Emeric Brunb982a3d2010-01-04 15:45:53 +01005746 /* find the target table for 'stick' rules */
5747 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5748 struct proxy *target;
5749
Emeric Brun1d33b292010-01-04 15:47:17 +01005750 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5751 if (mrule->flags & STK_IS_STORE)
5752 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5753
Emeric Brunb982a3d2010-01-04 15:45:53 +01005754 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005755 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 else
5757 target = curproxy;
5758
5759 if (!target) {
5760 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5761 curproxy->id, mrule->table.name);
5762 cfgerr++;
5763 }
5764 else if (target->table.size == 0) {
5765 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5766 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5767 cfgerr++;
5768 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005769 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005770 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5771 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5772 cfgerr++;
5773 }
5774 else {
5775 free((void *)mrule->table.name);
5776 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005777 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005778 }
5779 }
5780
5781 /* find the target table for 'store response' rules */
5782 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5783 struct proxy *target;
5784
Emeric Brun1d33b292010-01-04 15:47:17 +01005785 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5786
Emeric Brunb982a3d2010-01-04 15:45:53 +01005787 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005788 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005789 else
5790 target = curproxy;
5791
5792 if (!target) {
5793 Alert("Proxy '%s': unable to find store table '%s'.\n",
5794 curproxy->id, mrule->table.name);
5795 cfgerr++;
5796 }
5797 else if (target->table.size == 0) {
5798 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5799 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5800 cfgerr++;
5801 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005802 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005803 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5804 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5805 cfgerr++;
5806 }
5807 else {
5808 free((void *)mrule->table.name);
5809 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005810 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005811 }
5812 }
5813
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005814 /* find the target table for 'tcp-request' layer 4 rules */
5815 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5816 struct proxy *target;
5817
Willy Tarreau56123282010-08-06 19:06:56 +02005818 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005819 continue;
5820
5821 if (trule->act_prm.trk_ctr.table.n)
5822 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5823 else
5824 target = curproxy;
5825
5826 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005827 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5828 curproxy->id, trule->act_prm.trk_ctr.table.n,
5829 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005830 cfgerr++;
5831 }
5832 else if (target->table.size == 0) {
5833 Alert("Proxy '%s': table '%s' used but not configured.\n",
5834 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5835 cfgerr++;
5836 }
5837 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005838 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 +02005839 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5840 cfgerr++;
5841 }
5842 else {
5843 free(trule->act_prm.trk_ctr.table.n);
5844 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005845 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005846 * to pass a list of counters to track and allocate them right here using
5847 * stktable_alloc_data_type().
5848 */
5849 }
5850 }
5851
Willy Tarreaud1f96522010-08-03 19:34:32 +02005852 /* find the target table for 'tcp-request' layer 6 rules */
5853 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5854 struct proxy *target;
5855
Willy Tarreau56123282010-08-06 19:06:56 +02005856 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005857 continue;
5858
5859 if (trule->act_prm.trk_ctr.table.n)
5860 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5861 else
5862 target = curproxy;
5863
5864 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005865 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5866 curproxy->id, trule->act_prm.trk_ctr.table.n,
5867 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005868 cfgerr++;
5869 }
5870 else if (target->table.size == 0) {
5871 Alert("Proxy '%s': table '%s' used but not configured.\n",
5872 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5873 cfgerr++;
5874 }
5875 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005876 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 +02005877 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5878 cfgerr++;
5879 }
5880 else {
5881 free(trule->act_prm.trk_ctr.table.n);
5882 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005883 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005884 * to pass a list of counters to track and allocate them right here using
5885 * stktable_alloc_data_type().
5886 */
5887 }
5888 }
5889
Emeric Brun32da3c42010-09-23 18:39:19 +02005890 if (curproxy->table.peers.name) {
5891 struct peers *curpeers = peers;
5892
5893 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5894 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5895 free((void *)curproxy->table.peers.name);
5896 curproxy->table.peers.p = peers;
5897 break;
5898 }
5899 }
5900
5901 if (!curpeers) {
5902 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5903 curproxy->id, curproxy->table.peers.name);
5904 cfgerr++;
5905 }
5906 else if (!curpeers->peers_fe) {
5907 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5908 curproxy->id, curpeers->id);
5909 cfgerr++;
5910 }
5911 }
5912
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005913 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5914 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005915 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5916 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5917 "proxy", curproxy->id);
5918 cfgerr++;
5919 goto out_uri_auth_compat;
5920 }
5921
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005922 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005923 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005924 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005925 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005926
Willy Tarreau95fa4692010-02-01 13:05:50 +01005927 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5928 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005929
5930 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005931 uri_auth_compat_req[i++] = "realm";
5932 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5933 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005934
Willy Tarreau95fa4692010-02-01 13:05:50 +01005935 uri_auth_compat_req[i++] = "unless";
5936 uri_auth_compat_req[i++] = "{";
5937 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5938 uri_auth_compat_req[i++] = "}";
5939 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005940
Willy Tarreau95fa4692010-02-01 13:05:50 +01005941 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5942 if (!req_acl) {
5943 cfgerr++;
5944 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005945 }
5946
Willy Tarreau95fa4692010-02-01 13:05:50 +01005947 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5948
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005949 if (curproxy->uri_auth->auth_realm) {
5950 free(curproxy->uri_auth->auth_realm);
5951 curproxy->uri_auth->auth_realm = NULL;
5952 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005953
5954 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005955 }
5956out_uri_auth_compat:
5957
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005958 cfgerr += acl_find_targets(curproxy);
5959
Willy Tarreau2738a142006-07-08 17:28:09 +02005960 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005961 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005962 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005963 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005964 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005965 " | While not properly invalid, you will certainly encounter various problems\n"
5966 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005967 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005968 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005969 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005970 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005971
Willy Tarreau1fa31262007-12-03 00:36:16 +01005972 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5973 * We must still support older configurations, so let's find out whether those
5974 * parameters have been set or must be copied from contimeouts.
5975 */
5976 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005977 if (!curproxy->timeout.tarpit ||
5978 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005979 /* tarpit timeout not set. We search in the following order:
5980 * default.tarpit, curr.connect, default.connect.
5981 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005982 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005983 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005984 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005985 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005986 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005987 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005988 }
5989 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005990 (!curproxy->timeout.queue ||
5991 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005992 /* queue timeout not set. We search in the following order:
5993 * default.queue, curr.connect, default.connect.
5994 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005995 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005996 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005997 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005998 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005999 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006000 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006001 }
6002 }
6003
Willy Tarreau07a54902010-03-29 18:33:29 +02006004 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006005 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6006 curproxy->check_req = (char *)malloc(curproxy->check_len);
6007 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006008 }
6009
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006010 /* The small pools required for the capture lists */
6011 if (curproxy->nb_req_cap)
6012 curproxy->req_cap_pool = create_pool("ptrcap",
6013 curproxy->nb_req_cap * sizeof(char *),
6014 MEM_F_SHARED);
6015 if (curproxy->nb_rsp_cap)
6016 curproxy->rsp_cap_pool = create_pool("ptrcap",
6017 curproxy->nb_rsp_cap * sizeof(char *),
6018 MEM_F_SHARED);
6019
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006020 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6021 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6022 MEM_F_SHARED);
6023
Willy Tarreau86034312006-12-29 00:10:33 +01006024 /* for backwards compatibility with "listen" instances, if
6025 * fullconn is not set but maxconn is set, then maxconn
6026 * is used.
6027 */
6028 if (!curproxy->fullconn)
6029 curproxy->fullconn = curproxy->maxconn;
6030
Willy Tarreaubaaee002006-06-26 02:48:02 +02006031 /* first, we will invert the servers list order */
6032 newsrv = NULL;
6033 while (curproxy->srv) {
6034 struct server *next;
6035
6036 next = curproxy->srv->next;
6037 curproxy->srv->next = newsrv;
6038 newsrv = curproxy->srv;
6039 if (!next)
6040 break;
6041 curproxy->srv = next;
6042 }
6043
Willy Tarreaudd701652010-05-25 23:03:02 +02006044 /* assign automatic UIDs to servers which don't have one yet */
6045 next_id = 1;
6046 newsrv = curproxy->srv;
6047 while (newsrv != NULL) {
6048 if (!newsrv->puid) {
6049 /* server ID not set, use automatic numbering with first
6050 * spare entry starting with next_svid.
6051 */
6052 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6053 newsrv->conf.id.key = newsrv->puid = next_id;
6054 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6055 }
6056 next_id++;
6057 newsrv = newsrv->next;
6058 }
6059
Willy Tarreau20697042007-11-15 23:26:18 +01006060 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006061 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006063 /* We have to initialize the server lookup mechanism depending
6064 * on what LB algorithm was choosen.
6065 */
6066
6067 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6068 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6069 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006070 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6071 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6072 init_server_map(curproxy);
6073 } else {
6074 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6075 fwrr_init_server_groups(curproxy);
6076 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006077 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006078
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006079 case BE_LB_KIND_LC:
6080 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006081 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006082 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006083
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006084 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006085 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6086 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6087 chash_init_server_tree(curproxy);
6088 } else {
6089 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6090 init_server_map(curproxy);
6091 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006092 break;
6093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006094
6095 if (curproxy->options & PR_O_LOGASAP)
6096 curproxy->to_log &= ~LW_BYTES;
6097
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006098 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6099 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6100 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6101 proxy_type_str(curproxy), curproxy->id);
6102 err_code |= ERR_WARN;
6103 }
6104
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006105 if (curproxy->mode != PR_MODE_HTTP) {
6106 int optnum;
6107
6108 if (curproxy->options & PR_O_COOK_ANY) {
6109 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6110 proxy_type_str(curproxy), curproxy->id);
6111 err_code |= ERR_WARN;
6112 }
6113
6114 if (curproxy->uri_auth) {
6115 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6116 proxy_type_str(curproxy), curproxy->id);
6117 err_code |= ERR_WARN;
6118 curproxy->uri_auth = NULL;
6119 }
6120
6121 if (curproxy->options & PR_O_FWDFOR) {
6122 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6123 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6124 err_code |= ERR_WARN;
6125 curproxy->options &= ~PR_O_FWDFOR;
6126 }
6127
6128 if (curproxy->options & PR_O_ORGTO) {
6129 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6130 "originalto", proxy_type_str(curproxy), curproxy->id);
6131 err_code |= ERR_WARN;
6132 curproxy->options &= ~PR_O_ORGTO;
6133 }
6134
6135 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6136 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6137 (curproxy->cap & cfg_opts[optnum].cap) &&
6138 (curproxy->options & cfg_opts[optnum].val)) {
6139 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6140 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6141 err_code |= ERR_WARN;
6142 curproxy->options &= ~cfg_opts[optnum].val;
6143 }
6144 }
6145
6146 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6147 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6148 (curproxy->cap & cfg_opts2[optnum].cap) &&
6149 (curproxy->options2 & cfg_opts2[optnum].val)) {
6150 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6151 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6152 err_code |= ERR_WARN;
6153 curproxy->options2 &= ~cfg_opts2[optnum].val;
6154 }
6155 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006156
Willy Tarreauefa5f512010-03-30 20:13:29 +02006157#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006158 if (curproxy->bind_hdr_occ) {
6159 curproxy->bind_hdr_occ = 0;
6160 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6161 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6162 err_code |= ERR_WARN;
6163 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006164#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006165 }
6166
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006168 * ensure that we're not cross-dressing a TCP server into HTTP.
6169 */
6170 newsrv = curproxy->srv;
6171 while (newsrv != NULL) {
6172 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006173 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6174 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006175 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006176 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006177
Willy Tarreauefa5f512010-03-30 20:13:29 +02006178#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006179 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6180 newsrv->bind_hdr_occ = 0;
6181 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6182 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6183 err_code |= ERR_WARN;
6184 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006185#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006186 newsrv = newsrv->next;
6187 }
6188
6189 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 * If this server supports a maxconn parameter, it needs a dedicated
6191 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006192 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 */
6194 newsrv = curproxy->srv;
6195 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006196 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006197 /* Only 'minconn' was specified, or it was higher than or equal
6198 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6199 * this will avoid further useless expensive computations.
6200 */
6201 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006202 } else if (newsrv->maxconn && !newsrv->minconn) {
6203 /* minconn was not specified, so we set it to maxconn */
6204 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006205 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006206 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6207 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006208 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 }
6210
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006211 if (newsrv->trackit) {
6212 struct proxy *px;
6213 struct server *srv;
6214 char *pname, *sname;
6215
6216 pname = newsrv->trackit;
6217 sname = strrchr(pname, '/');
6218
6219 if (sname)
6220 *sname++ = '\0';
6221 else {
6222 sname = pname;
6223 pname = NULL;
6224 }
6225
6226 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006227 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006228 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006229 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6230 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006231 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006232 cfgerr++;
6233 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006234 }
6235 } else
6236 px = curproxy;
6237
6238 srv = findserver(px, sname);
6239 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006240 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6241 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006242 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006243 cfgerr++;
6244 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006245 }
6246
6247 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006248 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006249 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006250 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006251 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006252 cfgerr++;
6253 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006254 }
6255
6256 if (curproxy != px &&
6257 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006258 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006259 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006260 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006261 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006262 cfgerr++;
6263 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006264 }
6265
6266 newsrv->tracked = srv;
6267 newsrv->tracknext = srv->tracknext;
6268 srv->tracknext = newsrv;
6269
6270 free(newsrv->trackit);
6271 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006272 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 newsrv = newsrv->next;
6274 }
6275
Willy Tarreauc1a21672009-08-16 22:37:44 +02006276 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006277 curproxy->accept = frontend_accept;
6278
Willy Tarreauc1a21672009-08-16 22:37:44 +02006279 if (curproxy->tcp_req.inspect_delay ||
6280 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006281 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006282
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006283 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006284 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006285 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006286 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006287
6288 /* both TCP and HTTP must check switching rules */
6289 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6290 }
6291
6292 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006293 if (curproxy->tcp_req.inspect_delay ||
6294 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6295 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6296
Emeric Brun97679e72010-09-23 17:56:44 +02006297 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6298 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6299
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006300 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006301 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006302 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006303 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006304
6305 /* If the backend does requires RDP cookie persistence, we have to
6306 * enable the corresponding analyser.
6307 */
6308 if (curproxy->options2 & PR_O2_RDPC_PRST)
6309 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6310 }
6311
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006312 listener = NULL;
6313 while (curproxy->listen) {
6314 struct listener *next;
6315
6316 next = curproxy->listen->next;
6317 curproxy->listen->next = listener;
6318 listener = curproxy->listen;
6319
6320 if (!next)
6321 break;
6322
6323 curproxy->listen = next;
6324 }
6325
Willy Tarreaue6b98942007-10-29 01:09:36 +01006326 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006327 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006328 listener = curproxy->listen;
6329 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006330 if (!listener->luid) {
6331 /* listener ID not set, use automatic numbering with first
6332 * spare entry starting with next_luid.
6333 */
6334 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6335 listener->conf.id.key = listener->luid = next_id;
6336 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006337 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006338 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006339
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006340 /* enable separate counters */
6341 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6342 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6343 if (!listener->name) {
6344 sprintf(trash, "sock-%d", listener->luid);
6345 listener->name = strdup(trash);
6346 }
6347 }
6348
Willy Tarreaue6b98942007-10-29 01:09:36 +01006349 if (curproxy->options & PR_O_TCP_NOLING)
6350 listener->options |= LI_O_NOLINGER;
6351 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006352 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006353 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006354 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006355 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006356 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006357 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006358
Willy Tarreau8a956912010-10-15 14:27:08 +02006359 if (listener->options & LI_O_ACC_PROXY)
6360 listener->analysers |= AN_REQ_DECODE_PROXY;
6361
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006362 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6363 listener->options |= LI_O_TCP_RULES;
6364
Willy Tarreaude3041d2010-05-31 10:56:17 +02006365 if (curproxy->mon_mask.s_addr)
6366 listener->options |= LI_O_CHK_MONNET;
6367
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006368 /* smart accept mode is automatic in HTTP mode */
6369 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6370 (curproxy->mode == PR_MODE_HTTP &&
6371 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6372 listener->options |= LI_O_NOQUICKACK;
6373
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006374 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006375 listener = listener->next;
6376 }
6377
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006378 /* Check multi-process mode compatibility for the current proxy */
6379 if (global.nbproc > 1) {
6380 int nbproc = 0;
6381 if (curproxy->bind_proc) {
6382 int proc;
6383 for (proc = 0; proc < global.nbproc; proc++) {
6384 if (curproxy->bind_proc & (1 << proc)) {
6385 nbproc++;
6386 }
6387 }
6388 } else {
6389 nbproc = global.nbproc;
6390 }
6391 if (curproxy->table.peers.name) {
6392 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6393 curproxy->id);
6394 cfgerr++;
6395 }
6396 if (nbproc > 1) {
6397 if (curproxy->uri_auth) {
6398 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6399 curproxy->id);
6400 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6401 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6402 curproxy->id);
6403 }
6404 }
6405 if (curproxy->appsession_name) {
6406 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6407 curproxy->id);
6408 }
6409 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6410 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6411 curproxy->id);
6412 }
6413 }
6414 }
6415
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 curproxy = curproxy->next;
6417 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006418
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006419 /* Check multi-process mode compatibility */
6420 if (global.nbproc > 1) {
6421 if (global.stats_fe) {
6422 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6423 }
6424 }
6425
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006426 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6427 struct auth_users *curuser;
6428 int g;
6429
6430 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6431 unsigned int group_mask = 0;
6432 char *group = NULL;
6433
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006434 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006435 continue;
6436
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006437 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006438
6439 for (g = 0; g < curuserlist->grpcnt; g++)
6440 if (!strcmp(curuserlist->groups[g], group))
6441 break;
6442
6443 if (g == curuserlist->grpcnt) {
6444 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6445 curuserlist->name, group, curuser->user);
6446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto out;
6448 }
6449
6450 group_mask |= (1 << g);
6451 }
6452
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006453 free(curuser->u.groups);
6454 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006455 }
6456
6457 for (g = 0; g < curuserlist->grpcnt; g++) {
6458 char *user = NULL;
6459
6460 if (!curuserlist->groupusers[g])
6461 continue;
6462
6463 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6464 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6465 if (!strcmp(curuser->user, user))
6466 break;
6467
6468 if (!curuser) {
6469 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6470 curuserlist->name, user, curuserlist->groups[g]);
6471 err_code |= ERR_ALERT | ERR_FATAL;
6472 goto out;
6473 }
6474
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006475 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006476 }
6477
6478 free(curuserlist->groupusers[g]);
6479 }
6480
6481 free(curuserlist->groupusers);
6482
6483#ifdef DEBUG_AUTH
6484 for (g = 0; g < curuserlist->grpcnt; g++) {
6485 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6486
6487 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6488 if (curuser->group_mask & (1 << g))
6489 fprintf(stderr, " %s", curuser->user);
6490 }
6491
6492 fprintf(stderr, "\n");
6493 }
6494#endif
6495
6496 }
6497
Willy Tarreau056f5682010-06-06 15:51:11 +02006498 /* initialize stick-tables on backend capable proxies. This must not
6499 * be done earlier because the data size may be discovered while parsing
6500 * other proxies.
6501 */
6502 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006503 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006504
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006505 /*
6506 * Recount currently required checks.
6507 */
6508
6509 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6510 int optnum;
6511
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006512 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6513 if (curproxy->options & cfg_opts[optnum].val)
6514 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006515
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006516 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6517 if (curproxy->options2 & cfg_opts2[optnum].val)
6518 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006519 }
6520
Willy Tarreaubb925012009-07-23 13:36:36 +02006521 if (cfgerr > 0)
6522 err_code |= ERR_ALERT | ERR_FATAL;
6523 out:
6524 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525}
6526
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006527/*
6528 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6529 * parsing sessions.
6530 */
6531void cfg_register_keywords(struct cfg_kw_list *kwl)
6532{
6533 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6534}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006535
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006536/*
6537 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6538 */
6539void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6540{
6541 LIST_DEL(&kwl->list);
6542 LIST_INIT(&kwl->list);
6543}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544
6545/*
6546 * Local variables:
6547 * c-indent-level: 8
6548 * c-basic-offset: 8
6549 * End:
6550 */