blob: d3223ff6df89bab38df3745a00237e3e18b7de39 [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 }
969 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
970 if (global.spread_checks != 0) {
971 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200972 err_code |= ERR_ALERT;
973 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200974 }
975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200979 }
980 global.spread_checks = atol(args[1]);
981 if (global.spread_checks < 0 || global.spread_checks > 50) {
982 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200983 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 }
986 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200987 struct cfg_kw_list *kwl;
988 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200989 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200990
991 list_for_each_entry(kwl, &cfg_keywords.list, list) {
992 for (index = 0; kwl->kw[index].kw != NULL; index++) {
993 if (kwl->kw[index].section != CFG_GLOBAL)
994 continue;
995 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
996 /* prepare error message just in case */
997 snprintf(trash, sizeof(trash),
998 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200999 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1000 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001001 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001002 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001003 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001004 else if (rc > 0) {
1005 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_WARN;
1007 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001008 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001010 }
1011 }
1012 }
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001017
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 out:
1019 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020}
1021
Willy Tarreau97cb7802010-01-03 20:23:58 +01001022/* Perform the most basic initialization of a proxy :
1023 * memset(), list_init(*), reset_timeouts(*).
1024 */
1025static void init_new_proxy(struct proxy *p)
1026{
1027 memset(p, 0, sizeof(struct proxy));
1028 LIST_INIT(&p->pendconns);
1029 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001030 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001031 LIST_INIT(&p->block_cond);
1032 LIST_INIT(&p->redirect_rules);
1033 LIST_INIT(&p->mon_fail_cond);
1034 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001035 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001036 LIST_INIT(&p->sticking_rules);
1037 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001038 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001039 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001040 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001041 LIST_INIT(&p->req_add);
1042 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001043
1044 /* Timeouts are defined as -1 */
1045 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001046 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001047}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001049void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001051 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 defproxy.mode = PR_MODE_TCP;
1053 defproxy.state = PR_STNEW;
1054 defproxy.maxconn = cfg_maxpconn;
1055 defproxy.conn_retries = CONN_RETRIES;
1056 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001057
1058 defproxy.defsrv.inter = DEF_CHKINTR;
1059 defproxy.defsrv.fastinter = 0;
1060 defproxy.defsrv.downinter = 0;
1061 defproxy.defsrv.rise = DEF_RISETIME;
1062 defproxy.defsrv.fall = DEF_FALLTIME;
1063 defproxy.defsrv.check_port = 0;
1064 defproxy.defsrv.maxqueue = 0;
1065 defproxy.defsrv.minconn = 0;
1066 defproxy.defsrv.maxconn = 0;
1067 defproxy.defsrv.slowstart = 0;
1068 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1069 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1070 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071}
1072
Willy Tarreauade5ec42010-01-28 19:33:49 +01001073
1074static int create_cond_regex_rule(const char *file, int line,
1075 struct proxy *px, int dir, int action, int flags,
1076 const char *cmd, const char *reg, const char *repl,
1077 const char **cond_start)
1078{
1079 regex_t *preg = NULL;
1080 const char *err;
1081 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001082 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001083
1084 if (px == &defproxy) {
1085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto err;
1088 }
1089
1090 if (*reg == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto err;
1094 }
1095
1096 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1097 err_code |= ERR_WARN;
1098
Willy Tarreau5321c422010-01-28 20:35:13 +01001099 if (cond_start &&
1100 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1101 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1102 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1103 file, line, cmd);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto err;
1106 }
1107 }
1108 else if (cond_start && **cond_start) {
1109 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1110 file, line, cmd, *cond_start);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto err;
1113 }
1114
1115 if (dir == ACL_DIR_REQ)
1116 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001117 else
1118 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001119
Willy Tarreauade5ec42010-01-28 19:33:49 +01001120 preg = calloc(1, sizeof(regex_t));
1121 if (!preg) {
1122 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1123 err_code = ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1128 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1129 err_code = ERR_ALERT | ERR_FATAL;
1130 goto err;
1131 }
1132
1133 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001134 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001135 if (repl && err) {
1136 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1137 file, line, cmd, *err);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto err;
1140 }
1141
1142 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1143 err_code |= ERR_WARN;
1144
1145 return err_code;
1146 err:
1147 free(preg);
1148 return err_code;
1149}
1150
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001152 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001153 * Returns the error code, 0 if OK, or any combination of :
1154 * - ERR_ABORT: must abort ASAP
1155 * - ERR_FATAL: we can continue parsing but not start the service
1156 * - ERR_WARN: a warning has been emitted
1157 * - ERR_ALERT: an alert has been emitted
1158 * Only the two first ones can stop processing, the two others are just
1159 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001161int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1162{
1163 static struct peers *curpeers = NULL;
1164 struct peer *newpeer = NULL;
1165 const char *err;
1166 int err_code = 0;
1167
1168 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1169
1170 err = invalid_char(args[1]);
1171 if (err) {
1172 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1173 file, linenum, *err, args[0], args[1]);
1174 err_code |= ERR_ALERT | ERR_FATAL;
1175 }
1176
1177 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1178 /*
1179 * If there are two proxies with the same name only following
1180 * combinations are allowed:
1181 */
1182 if (strcmp(curpeers->id, args[1]) == 0) {
1183 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1184 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1185 err_code |= ERR_WARN;
1186 }
1187 }
1188
1189 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1190 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1191 err_code |= ERR_ALERT | ERR_ABORT;
1192 goto out;
1193 }
1194
1195 curpeers->next = peers;
1196 peers = curpeers;
1197 curpeers->conf.file = file;
1198 curpeers->conf.line = linenum;
1199 curpeers->last_change = now.tv_sec;
1200 curpeers->id = strdup(args[1]);
1201 }
1202 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1203 char *rport, *raddr;
1204 short realport = 0;
1205 struct sockaddr_in *sk;
1206
1207 if (!*args[2]) {
1208 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1209 file, linenum, args[0]);
1210 err_code |= ERR_ALERT | ERR_FATAL;
1211 goto out;
1212 }
1213
1214 err = invalid_char(args[1]);
1215 if (err) {
1216 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1217 file, linenum, *err, args[1]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221
1222 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1224 err_code |= ERR_ALERT | ERR_ABORT;
1225 goto out;
1226 }
1227
1228 /* the peers are linked backwards first */
1229 curpeers->count++;
1230 newpeer->next = curpeers->remote;
1231 curpeers->remote = newpeer;
1232 newpeer->peers = curpeers;
1233 newpeer->conf.file = file;
1234 newpeer->conf.line = linenum;
1235
1236 newpeer->last_change = now.tv_sec;
1237 newpeer->id = strdup(args[1]);
1238
1239 raddr = strdup(args[2]);
1240 rport = strchr(raddr, ':');
1241 if (rport) {
1242 *rport++ = 0;
1243 realport = atol(rport);
1244 }
1245 if (!realport) {
1246 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250
1251 sk = str2sa(raddr);
1252 free(raddr);
1253 if (!sk) {
1254 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258 newpeer->addr = *sk;
1259 newpeer->addr.sin_port = htons(realport);
1260
1261 if (strcmp(newpeer->id, localpeer) == 0) {
1262 /* Current is local peer, it define a frontend */
1263 newpeer->local = 1;
1264
1265 if (!curpeers->peers_fe) {
1266 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1267 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1268 err_code |= ERR_ALERT | ERR_ABORT;
1269 goto out;
1270 }
1271 curpeers->peers_fe->parent = curpeers;
1272
1273 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1274 LIST_INIT(&(curpeers->peers_fe)->acl);
1275 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1276 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1277 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1278 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1279 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1280 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1281
1282 proxy_reset_timeouts(curpeers->peers_fe);
1283
1284 curpeers->peers_fe->last_change = now.tv_sec;
1285 curpeers->peers_fe->id = strdup(args[1]);
1286 curpeers->peers_fe->cap = PR_CAP_FE;
1287 curpeers->peers_fe->maxconn = 65000;
1288 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1289 curpeers->peers_fe->timeout.connect = 5000;
1290 curpeers->peers_fe->accept = peer_accept;
1291 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1292 if (!str2listener(args[2], curpeers->peers_fe)) {
1293 err_code |= ERR_FATAL;
1294 goto out;
1295 }
1296 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1297 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1298 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1299 curpeers->peers_fe->listen->accept = session_accept;
1300 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1301 curpeers->peers_fe->listen->handler = process_session;
1302 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1303 }
1304 }
1305 } /* neither "peer" nor "peers" */
1306 else if (*args[0] != 0) {
1307 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
1310 }
1311
1312out:
1313 return err_code;
1314}
1315
1316
Willy Tarreau3842f002009-06-14 11:39:52 +02001317int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
1319 static struct proxy *curproxy = NULL;
1320 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001321 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001322 int rc;
1323 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001324 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001325 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326
Willy Tarreau977b8e42006-12-29 14:19:17 +01001327 if (!strcmp(args[0], "listen"))
1328 rc = PR_CAP_LISTEN;
1329 else if (!strcmp(args[0], "frontend"))
1330 rc = PR_CAP_FE | PR_CAP_RS;
1331 else if (!strcmp(args[0], "backend"))
1332 rc = PR_CAP_BE | PR_CAP_RS;
1333 else if (!strcmp(args[0], "ruleset"))
1334 rc = PR_CAP_RS;
1335 else
1336 rc = PR_CAP_NONE;
1337
1338 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 if (!*args[1]) {
1340 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1341 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_ABORT;
1344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001346
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001347 err = invalid_char(args[1]);
1348 if (err) {
1349 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1350 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001352 }
1353
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001354 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1355 /*
1356 * If there are two proxies with the same name only following
1357 * combinations are allowed:
1358 *
1359 * listen backend frontend ruleset
1360 * listen - - - -
1361 * backend - - OK -
1362 * frontend - OK - -
1363 * ruleset - - - -
1364 */
1365
1366 if (!strcmp(curproxy->id, args[1]) &&
1367 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1368 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001369 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1370 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1371 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001372 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001373 }
1374 }
1375
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1377 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001378 err_code |= ERR_ALERT | ERR_ABORT;
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001381
Willy Tarreau97cb7802010-01-03 20:23:58 +01001382 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 curproxy->next = proxy;
1384 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001385 curproxy->conf.file = file;
1386 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001387 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001389 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390
1391 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001392 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001393 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001394 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_FATAL;
1396 goto out;
1397 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001398 new = curproxy->listen;
1399 while (new != last) {
1400 new->conf.file = file;
1401 new->conf.line = linenum;
1402 new = new->next;
1403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 global.maxsock++;
1405 }
1406
1407 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001408 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001409 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001410
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001413 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001414 curproxy->no_options = defproxy.no_options;
1415 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001416 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001417 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001418 curproxy->except_net = defproxy.except_net;
1419 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001420 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001421 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001423 if (defproxy.fwdfor_hdr_len) {
1424 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1425 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1426 }
1427
Willy Tarreaub86db342009-11-30 11:50:16 +01001428 if (defproxy.orgto_hdr_len) {
1429 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1430 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1431 }
1432
Willy Tarreau977b8e42006-12-29 14:19:17 +01001433 if (curproxy->cap & PR_CAP_FE) {
1434 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001435 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001436 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001437
1438 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001439 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1440 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001441
1442 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444
Willy Tarreau977b8e42006-12-29 14:19:17 +01001445 if (curproxy->cap & PR_CAP_BE) {
1446 curproxy->fullconn = defproxy.fullconn;
1447 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001449 if (defproxy.check_req) {
1450 curproxy->check_req = calloc(1, defproxy.check_len);
1451 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1452 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001453 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454
Willy Tarreau977b8e42006-12-29 14:19:17 +01001455 if (defproxy.cookie_name)
1456 curproxy->cookie_name = strdup(defproxy.cookie_name);
1457 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001458 if (defproxy.cookie_domain)
1459 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001460
Willy Tarreau31936852010-10-06 16:59:56 +02001461 if (defproxy.cookie_maxidle)
1462 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1463
1464 if (defproxy.cookie_maxlife)
1465 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1466
Emeric Brun647caf12009-06-30 17:57:00 +02001467 if (defproxy.rdp_cookie_name)
1468 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1469 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1470
Willy Tarreau01732802007-11-01 22:48:15 +01001471 if (defproxy.url_param_name)
1472 curproxy->url_param_name = strdup(defproxy.url_param_name);
1473 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001474
Benoitaffb4812009-03-25 13:02:10 +01001475 if (defproxy.hh_name)
1476 curproxy->hh_name = strdup(defproxy.hh_name);
1477 curproxy->hh_len = defproxy.hh_len;
1478 curproxy->hh_match_domain = defproxy.hh_match_domain;
1479
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001480 if (defproxy.iface_name)
1481 curproxy->iface_name = strdup(defproxy.iface_name);
1482 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001485 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 if (defproxy.capture_name)
1487 curproxy->capture_name = strdup(defproxy.capture_name);
1488 curproxy->capture_namelen = defproxy.capture_namelen;
1489 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001493 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001494 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001495 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001496 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 curproxy->uri_auth = defproxy.uri_auth;
1498 curproxy->mon_net = defproxy.mon_net;
1499 curproxy->mon_mask = defproxy.mon_mask;
1500 if (defproxy.monitor_uri)
1501 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1502 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001503 if (defproxy.defbe.name)
1504 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 }
1506
1507 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001508 curproxy->timeout.connect = defproxy.timeout.connect;
1509 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001510 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001511 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001512 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001513 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001514 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001515 curproxy->source_addr = defproxy.source_addr;
1516 }
1517
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 curproxy->mode = defproxy.mode;
1519 curproxy->logfac1 = defproxy.logfac1;
1520 curproxy->logsrv1 = defproxy.logsrv1;
1521 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001522 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 curproxy->logfac2 = defproxy.logfac2;
1524 curproxy->logsrv2 = defproxy.logsrv2;
1525 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001526 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001528 curproxy->conf.used_listener_id = EB_ROOT;
1529 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001530
Willy Tarreau93893792009-07-23 13:19:11 +02001531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 }
1533 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1534 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001535 /* FIXME-20070101: we should do this too at the end of the
1536 * config parsing to free all default values.
1537 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001538 free(defproxy.check_req);
1539 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001540 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001541 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001542 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001543 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001544 free(defproxy.capture_name);
1545 free(defproxy.monitor_uri);
1546 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001547 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001548 free(defproxy.fwdfor_hdr_name);
1549 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001550 free(defproxy.orgto_hdr_name);
1551 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001552
Willy Tarreaua534fea2008-08-03 12:19:50 +02001553 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001554 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001555
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 /* we cannot free uri_auth because it might already be used */
1557 init_default_instance();
1558 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001559 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 }
1562 else if (curproxy == NULL) {
1563 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 }
1567
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568
1569 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001571 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001572 int cur_arg;
1573
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 if (curproxy == &defproxy) {
1575 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001580 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581
Emeric Bruned760922010-10-22 17:59:25 +02001582 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001583 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001588
1589 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001590
1591 /* NOTE: the following line might create several listeners if there
1592 * are comma-separated IPs or port ranges. So all further processing
1593 * will have to be applied to all listeners created after last_listen.
1594 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001595 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
1598 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001599
Willy Tarreau90a570f2009-10-04 20:54:54 +02001600 new_listen = curproxy->listen;
1601 while (new_listen != last_listen) {
1602 new_listen->conf.file = file;
1603 new_listen->conf.line = linenum;
1604 new_listen = new_listen->next;
1605 }
1606
Emeric Bruned760922010-10-22 17:59:25 +02001607 /* Set default global rights and owner for unix bind */
1608 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1609 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1610 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001611 cur_arg = 2;
1612 while (*(args[cur_arg])) {
1613 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1614#ifdef SO_BINDTODEVICE
1615 struct listener *l;
1616
Emeric Bruned760922010-10-22 17:59:25 +02001617 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1618 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1619 file, linenum, args[0], args[cur_arg]);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001624 if (!*args[cur_arg + 1]) {
1625 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001629 }
1630
1631 for (l = curproxy->listen; l != last_listen; l = l->next)
1632 l->interface = strdup(args[cur_arg + 1]);
1633
1634 global.last_checks |= LSTCHK_NETADM;
1635
1636 cur_arg += 2;
1637 continue;
1638#else
1639 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1640 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001643#endif
1644 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001645 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1646#ifdef TCP_MAXSEG
1647 struct listener *l;
1648 int mss;
1649
Emeric Bruned760922010-10-22 17:59:25 +02001650 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1651 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1652 file, linenum, args[0], args[cur_arg]);
1653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
1656
Willy Tarreaube1b9182009-06-14 18:48:19 +02001657 if (!*args[cur_arg + 1]) {
1658 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001662 }
1663
1664 mss = str2uic(args[cur_arg + 1]);
1665 if (mss < 1 || mss > 65535) {
1666 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001670 }
1671
1672 for (l = curproxy->listen; l != last_listen; l = l->next)
1673 l->maxseg = mss;
1674
1675 cur_arg += 2;
1676 continue;
1677#else
1678 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1679 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001682#endif
1683 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001684
1685 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1686#ifdef TCP_DEFER_ACCEPT
1687 struct listener *l;
1688
1689 for (l = curproxy->listen; l != last_listen; l = l->next)
1690 l->options |= LI_O_DEF_ACCEPT;
1691
1692 cur_arg ++;
1693 continue;
1694#else
1695 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1696 file, linenum, args[0], args[cur_arg]);
1697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
1699#endif
1700 }
1701
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001702 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001703#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001704 struct listener *l;
1705
Emeric Bruned760922010-10-22 17:59:25 +02001706 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1707 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1708 file, linenum, args[0], args[cur_arg]);
1709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
1711 }
1712
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713 for (l = curproxy->listen; l != last_listen; l = l->next)
1714 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001715
1716 cur_arg ++;
1717 continue;
1718#else
1719 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1720 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001723#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001724 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001725
Willy Tarreau8a956912010-10-15 14:27:08 +02001726 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1727 struct listener *l;
1728
1729 for (l = curproxy->listen; l != last_listen; l = l->next)
1730 l->options |= LI_O_ACC_PROXY;
1731
1732 cur_arg ++;
1733 continue;
1734 }
1735
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001736 if (!strcmp(args[cur_arg], "name")) {
1737 struct listener *l;
1738
1739 for (l = curproxy->listen; l != last_listen; l = l->next)
1740 l->name = strdup(args[cur_arg + 1]);
1741
1742 cur_arg += 2;
1743 continue;
1744 }
1745
1746 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001747 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001748 struct listener *l;
1749
1750 if (curproxy->listen->next != last_listen) {
1751 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1752 file, linenum, args[cur_arg]);
1753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
1755 }
1756
1757 if (!*args[cur_arg + 1]) {
1758 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1759 file, linenum, args[cur_arg]);
1760 err_code |= ERR_ALERT | ERR_FATAL;
1761 goto out;
1762 }
1763
1764 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001765 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001766
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001767 if (curproxy->listen->luid <= 0) {
1768 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001769 file, linenum);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001774 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1775 if (node) {
1776 l = container_of(node, struct listener, conf.id);
1777 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1778 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1783
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001784 cur_arg += 2;
1785 continue;
1786 }
1787
Emeric Bruned760922010-10-22 17:59:25 +02001788 if (!strcmp(args[cur_arg], "mode")) {
1789
1790 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1791 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1798
1799 cur_arg += 2;
1800 continue;
1801 }
1802
1803 if (!strcmp(args[cur_arg], "uid")) {
1804
1805 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1806 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1807 file, linenum, args[0], args[cur_arg]);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1813 cur_arg += 2;
1814 continue;
1815 }
1816
1817 if (!strcmp(args[cur_arg], "gid")) {
1818
1819 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1820 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1821 file, linenum, args[0], args[cur_arg]);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825
1826 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1827 cur_arg += 2;
1828 continue;
1829 }
1830
1831 if (!strcmp(args[cur_arg], "user")) {
1832 struct passwd *user;
1833
1834 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1835 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1836 file, linenum, args[0], args[cur_arg]);
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840 user = getpwnam(args[cur_arg + 1]);
1841 if (!user) {
1842 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1843 file, linenum, args[0], args[cur_arg + 1 ]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847
1848 curproxy->listen->perm.ux.uid = user->pw_uid;
1849 cur_arg += 2;
1850 continue;
1851 }
1852
1853 if (!strcmp(args[cur_arg], "group")) {
1854 struct group *group;
1855
1856 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1857 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1858 file, linenum, args[0], args[cur_arg]);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862 group = getgrnam(args[cur_arg + 1]);
1863 if (!group) {
1864 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1865 file, linenum, args[0], args[cur_arg + 1 ]);
1866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
1868 }
1869
1870 curproxy->listen->perm.ux.gid = group->gr_gid;
1871 cur_arg += 2;
1872 continue;
1873 }
1874
Willy Tarreau8a956912010-10-15 14:27:08 +02001875 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 +01001876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 }
1883 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1884 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1885 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001891 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001892
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 /* flush useless bits */
1894 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001897 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001898 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900
Willy Tarreau1c47f852006-07-09 08:22:27 +02001901 if (!*args[1]) {
1902 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1903 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001906 }
1907
Willy Tarreaua534fea2008-08-03 12:19:50 +02001908 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001909 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001910 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001911 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001912 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1913
Willy Tarreau93893792009-07-23 13:19:11 +02001914 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1917 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1918 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1919 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1920 else {
1921 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
1925 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001926 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001927 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001928
1929 if (curproxy == &defproxy) {
1930 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001934 }
1935
1936 if (!*args[1]) {
1937 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001941 }
1942
1943 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001944 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001945
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001946 if (curproxy->uuid <= 0) {
1947 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001948 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_ALERT | ERR_FATAL;
1950 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001951 }
1952
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001953 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1954 if (node) {
1955 struct proxy *target = container_of(node, struct proxy, conf.id);
1956 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1957 file, linenum, proxy_type_str(curproxy), curproxy->id,
1958 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1959 err_code |= ERR_ALERT | ERR_FATAL;
1960 goto out;
1961 }
1962 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001963 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001964 else if (!strcmp(args[0], "description")) {
1965 int i, len=0;
1966 char *d;
1967
Cyril Bonté99ed3272010-01-24 23:29:44 +01001968 if (curproxy == &defproxy) {
1969 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1970 file, linenum, args[0]);
1971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
1973 }
1974
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001975 if (!*args[1]) {
1976 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1977 file, linenum, args[0]);
1978 return -1;
1979 }
1980
1981 for(i=1; *args[i]; i++)
1982 len += strlen(args[i])+1;
1983
1984 d = (char *)calloc(1, len);
1985 curproxy->desc = d;
1986
1987 d += sprintf(d, "%s", args[1]);
1988 for(i=2; *args[i]; i++)
1989 d += sprintf(d, " %s", args[i]);
1990
1991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1993 curproxy->state = PR_STSTOPPED;
1994 }
1995 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1996 curproxy->state = PR_STNEW;
1997 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001998 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1999 int cur_arg = 1;
2000 unsigned int set = 0;
2001
2002 while (*args[cur_arg]) {
2003 int u;
2004 if (strcmp(args[cur_arg], "all") == 0) {
2005 set = 0;
2006 break;
2007 }
2008 else if (strcmp(args[cur_arg], "odd") == 0) {
2009 set |= 0x55555555;
2010 }
2011 else if (strcmp(args[cur_arg], "even") == 0) {
2012 set |= 0xAAAAAAAA;
2013 }
2014 else {
2015 u = str2uic(args[cur_arg]);
2016 if (u < 1 || u > 32) {
2017 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002021 }
2022 if (u > global.nbproc) {
2023 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2024 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002025 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002026 }
2027 set |= 1 << (u - 1);
2028 }
2029 cur_arg++;
2030 }
2031 curproxy->bind_proc = set;
2032 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002033 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002034 if (curproxy == &defproxy) {
2035 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002038 }
2039
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002040 err = invalid_char(args[1]);
2041 if (err) {
2042 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2043 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002045 }
2046
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002047 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2048 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2049 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002052 }
2053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2055 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002059
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 if (*(args[1]) == 0) {
2061 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002066
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002067 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002068 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002069 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002070 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002071 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 curproxy->cookie_name = strdup(args[1]);
2073 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002074
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 cur_arg = 2;
2076 while (*(args[cur_arg])) {
2077 if (!strcmp(args[cur_arg], "rewrite")) {
2078 curproxy->options |= PR_O_COOK_RW;
2079 }
2080 else if (!strcmp(args[cur_arg], "indirect")) {
2081 curproxy->options |= PR_O_COOK_IND;
2082 }
2083 else if (!strcmp(args[cur_arg], "insert")) {
2084 curproxy->options |= PR_O_COOK_INS;
2085 }
2086 else if (!strcmp(args[cur_arg], "nocache")) {
2087 curproxy->options |= PR_O_COOK_NOC;
2088 }
2089 else if (!strcmp(args[cur_arg], "postonly")) {
2090 curproxy->options |= PR_O_COOK_POST;
2091 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002092 else if (!strcmp(args[cur_arg], "preserve")) {
2093 curproxy->options2 |= PR_O2_COOK_PSV;
2094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 else if (!strcmp(args[cur_arg], "prefix")) {
2096 curproxy->options |= PR_O_COOK_PFX;
2097 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002098 else if (!strcmp(args[cur_arg], "domain")) {
2099 if (!*args[cur_arg + 1]) {
2100 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2101 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002104 }
2105
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002106 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002107 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002108 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2109 " dots nor does not start with a dot."
2110 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002111 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002112 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002113 }
2114
2115 err = invalid_domainchar(args[cur_arg + 1]);
2116 if (err) {
2117 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2118 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002121 }
2122
Willy Tarreau68a897b2009-12-03 23:28:34 +01002123 if (!curproxy->cookie_domain) {
2124 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2125 } else {
2126 /* one domain was already specified, add another one by
2127 * building the string which will be returned along with
2128 * the cookie.
2129 */
2130 char *new_ptr;
2131 int new_len = strlen(curproxy->cookie_domain) +
2132 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2133 new_ptr = malloc(new_len);
2134 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2135 free(curproxy->cookie_domain);
2136 curproxy->cookie_domain = new_ptr;
2137 }
Willy Tarreau31936852010-10-06 16:59:56 +02002138 cur_arg++;
2139 }
2140 else if (!strcmp(args[cur_arg], "maxidle")) {
2141 unsigned int maxidle;
2142 const char *res;
2143
2144 if (!*args[cur_arg + 1]) {
2145 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2146 file, linenum, args[cur_arg]);
2147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
2149 }
2150
2151 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2152 if (res) {
2153 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2154 file, linenum, *res, args[cur_arg]);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158 curproxy->cookie_maxidle = maxidle;
2159 cur_arg++;
2160 }
2161 else if (!strcmp(args[cur_arg], "maxlife")) {
2162 unsigned int maxlife;
2163 const char *res;
2164
2165 if (!*args[cur_arg + 1]) {
2166 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2167 file, linenum, args[cur_arg]);
2168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
2171
2172 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2173 if (res) {
2174 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2175 file, linenum, *res, args[cur_arg]);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002180 cur_arg++;
2181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002183 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 +02002184 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 }
2188 cur_arg++;
2189 }
2190 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2191 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2192 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002193 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 }
2195
2196 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2197 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2198 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002201
2202 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2203 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2204 file, linenum);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002208 else if (!strcmp(args[0], "persist")) { /* persist */
2209 if (*(args[1]) == 0) {
2210 Alert("parsing [%s:%d] : missing persist method.\n",
2211 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002214 }
2215
2216 if (!strncmp(args[1], "rdp-cookie", 10)) {
2217 curproxy->options2 |= PR_O2_RDPC_PRST;
2218
Emeric Brunb982a3d2010-01-04 15:45:53 +01002219 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002220 const char *beg, *end;
2221
2222 beg = args[1] + 11;
2223 end = strchr(beg, ')');
2224
2225 if (!end || end == beg) {
2226 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2227 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002230 }
2231
2232 free(curproxy->rdp_cookie_name);
2233 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2234 curproxy->rdp_cookie_len = end-beg;
2235 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002236 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002237 free(curproxy->rdp_cookie_name);
2238 curproxy->rdp_cookie_name = strdup("msts");
2239 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2240 }
2241 else { /* syntax */
2242 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2243 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002246 }
2247 }
2248 else {
2249 Alert("parsing [%s:%d] : unknown persist method.\n",
2250 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002253 }
2254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002256 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002258 if (curproxy == &defproxy) {
2259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002266
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002268 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 }
2273 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002274 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 curproxy->appsession_name = strdup(args[1]);
2276 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2277 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002278 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2279 if (err) {
2280 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2281 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002284 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002285 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002286
Willy Tarreau51041c72007-09-09 21:56:53 +02002287 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2288 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_ABORT;
2290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002292
2293 cur_arg = 6;
2294 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002295 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2296 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002297 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002298 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002299 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002300 } else if (!strcmp(args[cur_arg], "prefix")) {
2301 curproxy->options2 |= PR_O2_AS_PFX;
2302 } else if (!strcmp(args[cur_arg], "mode")) {
2303 if (!*args[cur_arg + 1]) {
2304 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2305 file, linenum, args[0], args[cur_arg]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 cur_arg++;
2311 if (!strcmp(args[cur_arg], "query-string")) {
2312 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2313 curproxy->options2 |= PR_O2_AS_M_QS;
2314 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2315 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2316 curproxy->options2 |= PR_O2_AS_M_PP;
2317 } else {
2318 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002323 cur_arg++;
2324 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 } /* Url App Session */
2326 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002327 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002331 if (curproxy == &defproxy) {
2332 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
2335 }
2336
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 if (*(args[4]) == 0) {
2338 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2339 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002343 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 curproxy->capture_name = strdup(args[2]);
2345 curproxy->capture_namelen = strlen(curproxy->capture_name);
2346 curproxy->capture_len = atol(args[4]);
2347 if (curproxy->capture_len >= CAPTURE_LEN) {
2348 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2349 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 curproxy->capture_len = CAPTURE_LEN - 1;
2352 }
2353 curproxy->to_log |= LW_COOKIE;
2354 }
2355 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2356 struct cap_hdr *hdr;
2357
2358 if (curproxy == &defproxy) {
2359 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 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
2363
2364 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2365 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2366 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
2370
2371 hdr = calloc(sizeof(struct cap_hdr), 1);
2372 hdr->next = curproxy->req_cap;
2373 hdr->name = strdup(args[3]);
2374 hdr->namelen = strlen(args[3]);
2375 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002376 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 hdr->index = curproxy->nb_req_cap++;
2378 curproxy->req_cap = hdr;
2379 curproxy->to_log |= LW_REQHDR;
2380 }
2381 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2382 struct cap_hdr *hdr;
2383
2384 if (curproxy == &defproxy) {
2385 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 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 }
2389
2390 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2391 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2392 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396 hdr = calloc(sizeof(struct cap_hdr), 1);
2397 hdr->next = curproxy->rsp_cap;
2398 hdr->name = strdup(args[3]);
2399 hdr->namelen = strlen(args[3]);
2400 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002401 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 hdr->index = curproxy->nb_rsp_cap++;
2403 curproxy->rsp_cap = hdr;
2404 curproxy->to_log |= LW_RSPHDR;
2405 }
2406 else {
2407 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2408 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002414 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002416
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 if (*(args[1]) == 0) {
2418 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 }
2423 curproxy->conn_retries = atol(args[1]);
2424 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002425 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2426 struct req_acl_rule *req_acl;
2427
2428 if (curproxy == &defproxy) {
2429 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433
2434
2435 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2436 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2437 file, linenum, args[0]);
2438 err_code |= ERR_WARN;
2439 }
2440
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002441 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002442
2443 if (!req_acl) {
2444 err_code |= ERR_ALERT | ERR_ABORT;
2445 goto out;
2446 }
2447
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002448 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002449 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2450 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002451 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002452 if (curproxy == &defproxy) {
2453 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002456 }
2457
Willy Tarreauef6494c2010-01-28 17:12:36 +01002458 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002459 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002463 }
2464
Willy Tarreauef6494c2010-01-28 17:12:36 +01002465 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002466 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002470 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002471
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002472 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002473 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002474 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002475 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002476 struct redirect_rule *rule;
2477 int cur_arg;
2478 int type = REDIRECT_TYPE_NONE;
2479 int code = 302;
2480 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002481 char *cookie = NULL;
2482 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002483 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002484
Cyril Bonté99ed3272010-01-24 23:29:44 +01002485 if (curproxy == &defproxy) {
2486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002491 cur_arg = 1;
2492 while (*(args[cur_arg])) {
2493 if (!strcmp(args[cur_arg], "location")) {
2494 if (!*args[cur_arg + 1]) {
2495 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2496 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002499 }
2500
2501 type = REDIRECT_TYPE_LOCATION;
2502 cur_arg++;
2503 destination = args[cur_arg];
2504 }
2505 else if (!strcmp(args[cur_arg], "prefix")) {
2506 if (!*args[cur_arg + 1]) {
2507 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2508 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002511 }
2512
2513 type = REDIRECT_TYPE_PREFIX;
2514 cur_arg++;
2515 destination = args[cur_arg];
2516 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002517 else if (!strcmp(args[cur_arg], "set-cookie")) {
2518 if (!*args[cur_arg + 1]) {
2519 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2520 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002523 }
2524
2525 cur_arg++;
2526 cookie = args[cur_arg];
2527 cookie_set = 1;
2528 }
2529 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2530 if (!*args[cur_arg + 1]) {
2531 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2532 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002535 }
2536
2537 cur_arg++;
2538 cookie = args[cur_arg];
2539 cookie_set = 0;
2540 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002541 else if (!strcmp(args[cur_arg],"code")) {
2542 if (!*args[cur_arg + 1]) {
2543 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2544 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002547 }
2548 cur_arg++;
2549 code = atol(args[cur_arg]);
2550 if (code < 301 || code > 303) {
2551 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2552 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 }
2556 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002557 else if (!strcmp(args[cur_arg],"drop-query")) {
2558 flags |= REDIRECT_FLAG_DROP_QS;
2559 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002560 else if (!strcmp(args[cur_arg],"append-slash")) {
2561 flags |= REDIRECT_FLAG_APPEND_SLASH;
2562 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002563 else if (strcmp(args[cur_arg], "if") == 0 ||
2564 strcmp(args[cur_arg], "unless") == 0) {
2565 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2566 if (!cond) {
2567 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2568 file, linenum, args[0]);
2569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
2571 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002572 break;
2573 }
2574 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002575 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 +02002576 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 }
2580 cur_arg++;
2581 }
2582
2583 if (type == REDIRECT_TYPE_NONE) {
2584 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2585 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002588 }
2589
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002590 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2591 rule->cond = cond;
2592 rule->rdr_str = strdup(destination);
2593 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002594 if (cookie) {
2595 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002596 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002597 */
2598 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002599 if (cookie_set) {
2600 rule->cookie_str = malloc(rule->cookie_len + 10);
2601 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2602 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2603 rule->cookie_len += 9;
2604 } else {
2605 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002606 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002607 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2608 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002609 }
2610 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002611 rule->type = type;
2612 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002613 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002614 LIST_INIT(&rule->list);
2615 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002616 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002617 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002618 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002619 struct switching_rule *rule;
2620
Willy Tarreaub099aca2008-10-12 17:26:37 +02002621 if (curproxy == &defproxy) {
2622 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002625 }
2626
Willy Tarreau55ea7572007-06-17 19:56:27 +02002627 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002629
2630 if (*(args[1]) == 0) {
2631 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002634 }
2635
Willy Tarreauef6494c2010-01-28 17:12:36 +01002636 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002637 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2638 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002641 }
2642
Willy Tarreauef6494c2010-01-28 17:12:36 +01002643 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002644 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002645 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002648 }
2649
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002650 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002651
Willy Tarreau55ea7572007-06-17 19:56:27 +02002652 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2653 rule->cond = cond;
2654 rule->be.name = strdup(args[1]);
2655 LIST_INIT(&rule->list);
2656 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2657 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002658 else if ((!strcmp(args[0], "force-persist")) ||
2659 (!strcmp(args[0], "ignore-persist"))) {
2660 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002661
2662 if (curproxy == &defproxy) {
2663 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
2668 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2669 err_code |= ERR_WARN;
2670
Willy Tarreauef6494c2010-01-28 17:12:36 +01002671 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002672 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2673 file, linenum, args[0]);
2674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
2676 }
2677
Willy Tarreauef6494c2010-01-28 17:12:36 +01002678 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002679 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2680 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002685 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002686
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002687 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002688 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002689 if (!strcmp(args[0], "force-persist")) {
2690 rule->type = PERSIST_TYPE_FORCE;
2691 } else {
2692 rule->type = PERSIST_TYPE_IGNORE;
2693 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002694 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002695 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002696 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002697 else if (!strcmp(args[0], "stick-table")) {
2698 int myidx = 1;
2699
Emeric Brun32da3c42010-09-23 18:39:19 +02002700 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002701 curproxy->table.type = (unsigned int)-1;
2702 while (*args[myidx]) {
2703 const char *err;
2704
2705 if (strcmp(args[myidx], "size") == 0) {
2706 myidx++;
2707 if (!*(args[myidx])) {
2708 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2709 file, linenum, args[myidx-1]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2714 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2715 file, linenum, *err, args[myidx-1]);
2716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
2718 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002719 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002720 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002721 else if (strcmp(args[myidx], "peers") == 0) {
2722 myidx++;
2723 if (!*(args[myidx])) {
2724 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2725 file, linenum, args[myidx-1]);
2726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
2728 }
2729 curproxy->table.peers.name = strdup(args[myidx++]);
2730 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002731 else if (strcmp(args[myidx], "expire") == 0) {
2732 myidx++;
2733 if (!*(args[myidx])) {
2734 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2735 file, linenum, args[myidx-1]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
2738 }
2739 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2740 if (err) {
2741 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2742 file, linenum, *err, args[myidx-1]);
2743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
2745 }
2746 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002747 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002748 }
2749 else if (strcmp(args[myidx], "nopurge") == 0) {
2750 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002751 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002752 }
2753 else if (strcmp(args[myidx], "type") == 0) {
2754 myidx++;
2755 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2756 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2757 file, linenum, args[myidx]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002761 /* myidx already points to next arg */
2762 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002763 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002764 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002765 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002766
2767 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002768 nw = args[myidx];
2769 while (*nw) {
2770 /* the "store" keyword supports a comma-separated list */
2771 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002772 sa = NULL; /* store arg */
2773 while (*nw && *nw != ',') {
2774 if (*nw == '(') {
2775 *nw = 0;
2776 sa = ++nw;
2777 while (*nw != ')') {
2778 if (!*nw) {
2779 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2780 file, linenum, args[0], cw);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784 nw++;
2785 }
2786 *nw = '\0';
2787 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002788 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002789 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002790 if (*nw)
2791 *nw++ = '\0';
2792 type = stktable_get_data_type(cw);
2793 if (type < 0) {
2794 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2795 file, linenum, args[0], cw);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
Willy Tarreauac782882010-06-20 10:41:54 +02002799
2800 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2801 switch (err) {
2802 case PE_NONE: break;
2803 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002804 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2805 file, linenum, args[0], cw);
2806 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002807 break;
2808
2809 case PE_ARG_MISSING:
2810 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2811 file, linenum, args[0], cw);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814
2815 case PE_ARG_NOT_USED:
2816 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2817 file, linenum, args[0], cw);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
2820
2821 default:
2822 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2823 file, linenum, args[0], cw);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002826 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002827 }
2828 myidx++;
2829 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002830 else {
2831 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2832 file, linenum, args[myidx]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002835 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002836 }
2837
2838 if (!curproxy->table.size) {
2839 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2840 file, linenum);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844
2845 if (curproxy->table.type == (unsigned int)-1) {
2846 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2847 file, linenum);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851 }
2852 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002853 struct sticking_rule *rule;
2854 struct pattern_expr *expr;
2855 int myidx = 0;
2856 const char *name = NULL;
2857 int flags;
2858
2859 if (curproxy == &defproxy) {
2860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864
2865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2866 err_code |= ERR_WARN;
2867 goto out;
2868 }
2869
2870 myidx++;
2871 if ((strcmp(args[myidx], "store") == 0) ||
2872 (strcmp(args[myidx], "store-request") == 0)) {
2873 myidx++;
2874 flags = STK_IS_STORE;
2875 }
2876 else if (strcmp(args[myidx], "store-response") == 0) {
2877 myidx++;
2878 flags = STK_IS_STORE | STK_ON_RSP;
2879 }
2880 else if (strcmp(args[myidx], "match") == 0) {
2881 myidx++;
2882 flags = STK_IS_MATCH;
2883 }
2884 else if (strcmp(args[myidx], "on") == 0) {
2885 myidx++;
2886 flags = STK_IS_MATCH | STK_IS_STORE;
2887 }
2888 else {
2889 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
2894 if (*(args[myidx]) == 0) {
2895 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899
Emeric Brun485479d2010-09-23 18:02:19 +02002900 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002901 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002902 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906
2907 if (flags & STK_ON_RSP) {
2908 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2909 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2910 file, linenum, args[0], expr->fetch->kw);
2911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
2914 } else {
2915 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2916 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2917 file, linenum, args[0], expr->fetch->kw);
2918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920 }
2921 }
2922
2923 if (strcmp(args[myidx], "table") == 0) {
2924 myidx++;
2925 name = args[myidx++];
2926 }
2927
Willy Tarreauef6494c2010-01-28 17:12:36 +01002928 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2929 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002930 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2931 file, linenum, args[0]);
2932 err_code |= ERR_ALERT | ERR_FATAL;
2933 goto out;
2934 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002936 else if (*(args[myidx])) {
2937 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2938 file, linenum, args[0], args[myidx]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
Emeric Brun97679e72010-09-23 17:56:44 +02002942 if (flags & STK_ON_RSP)
2943 err_code |= warnif_cond_requires_req(cond, file, linenum);
2944 else
2945 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002946
Emeric Brunb982a3d2010-01-04 15:45:53 +01002947 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2948 rule->cond = cond;
2949 rule->expr = expr;
2950 rule->flags = flags;
2951 rule->table.name = name ? strdup(name) : NULL;
2952 LIST_INIT(&rule->list);
2953 if (flags & STK_ON_RSP)
2954 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2955 else
2956 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002961
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2963 curproxy->uri_auth = NULL; /* we must detach from the default config */
2964
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002965 if (!*args[1]) {
2966 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002967 } else if (!strcmp(args[1], "admin")) {
2968 struct stats_admin_rule *rule;
2969
2970 if (curproxy == &defproxy) {
2971 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975
2976 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2977 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2978 err_code |= ERR_ALERT | ERR_ABORT;
2979 goto out;
2980 }
2981
2982 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2983 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2984 file, linenum, args[0], args[1]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2989 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2990 file, linenum, args[0], args[1]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
2995 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2996
2997 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2998 rule->cond = cond;
2999 LIST_INIT(&rule->list);
3000 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 } else if (!strcmp(args[1], "uri")) {
3002 if (*(args[2]) == 0) {
3003 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3007 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_ABORT;
3009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
3011 } else if (!strcmp(args[1], "realm")) {
3012 if (*(args[2]) == 0) {
3013 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3017 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_ABORT;
3019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003021 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003022 unsigned interval;
3023
3024 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3025 if (err) {
3026 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3027 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003030 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3031 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_ABORT;
3033 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003034 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003035 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3036 struct req_acl_rule *req_acl;
3037
3038 if (curproxy == &defproxy) {
3039 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
3042 }
3043
3044 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3045 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3046 err_code |= ERR_ALERT | ERR_ABORT;
3047 goto out;
3048 }
3049
3050 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3051 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3052 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3053 file, linenum, args[0]);
3054 err_code |= ERR_WARN;
3055 }
3056
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003057 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003058
3059 if (!req_acl) {
3060 err_code |= ERR_ALERT | ERR_ABORT;
3061 goto out;
3062 }
3063
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003064 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003065 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3066
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 } else if (!strcmp(args[1], "auth")) {
3068 if (*(args[2]) == 0) {
3069 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3073 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_ABORT;
3075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 }
3077 } else if (!strcmp(args[1], "scope")) {
3078 if (*(args[2]) == 0) {
3079 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3083 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_ABORT;
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
3087 } else if (!strcmp(args[1], "enable")) {
3088 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_ALERT | ERR_ABORT;
3091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003093 } else if (!strcmp(args[1], "hide-version")) {
3094 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3095 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_ABORT;
3097 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003098 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003099 } else if (!strcmp(args[1], "show-legends")) {
3100 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3101 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3102 err_code |= ERR_ALERT | ERR_ABORT;
3103 goto out;
3104 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003105 } else if (!strcmp(args[1], "show-node")) {
3106
3107 if (*args[2]) {
3108 int i;
3109 char c;
3110
3111 for (i=0; args[2][i]; i++) {
3112 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003113 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3114 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003115 break;
3116 }
3117
3118 if (!i || args[2][i]) {
3119 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3120 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3121 file, linenum, args[0], args[1]);
3122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
3124 }
3125 }
3126
3127 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3128 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3129 err_code |= ERR_ALERT | ERR_ABORT;
3130 goto out;
3131 }
3132 } else if (!strcmp(args[1], "show-desc")) {
3133 char *desc = NULL;
3134
3135 if (*args[2]) {
3136 int i, len=0;
3137 char *d;
3138
3139 for(i=2; *args[i]; i++)
3140 len += strlen(args[i])+1;
3141
3142 desc = d = (char *)calloc(1, len);
3143
3144 d += sprintf(d, "%s", args[2]);
3145 for(i=3; *args[i]; i++)
3146 d += sprintf(d, " %s", args[i]);
3147 }
3148
3149 if (!*args[2] && !global.desc)
3150 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3151 file, linenum, args[1]);
3152 else {
3153 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3154 free(desc);
3155 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3156 err_code |= ERR_ALERT | ERR_ABORT;
3157 goto out;
3158 }
3159 free(desc);
3160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003162stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003163 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 +01003164 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
3168 }
3169 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003170 int optnum;
3171
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003172 if (*(args[1]) == '\0') {
3173 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003178
3179 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3180 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003181 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3182 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3183 file, linenum, cfg_opts[optnum].name);
3184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
3186 }
Willy Tarreau93893792009-07-23 13:19:11 +02003187 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3188 err_code |= ERR_WARN;
3189 goto out;
3190 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003191
Willy Tarreau3842f002009-06-14 11:39:52 +02003192 curproxy->no_options &= ~cfg_opts[optnum].val;
3193 curproxy->options &= ~cfg_opts[optnum].val;
3194
3195 switch (kwm) {
3196 case KWM_STD:
3197 curproxy->options |= cfg_opts[optnum].val;
3198 break;
3199 case KWM_NO:
3200 curproxy->no_options |= cfg_opts[optnum].val;
3201 break;
3202 case KWM_DEF: /* already cleared */
3203 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003204 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003205
Willy Tarreau93893792009-07-23 13:19:11 +02003206 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003207 }
3208 }
3209
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003210 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3211 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003212 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3213 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3214 file, linenum, cfg_opts2[optnum].name);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
Willy Tarreau93893792009-07-23 13:19:11 +02003218 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3219 err_code |= ERR_WARN;
3220 goto out;
3221 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003222
Willy Tarreau3842f002009-06-14 11:39:52 +02003223 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3224 curproxy->options2 &= ~cfg_opts2[optnum].val;
3225
3226 switch (kwm) {
3227 case KWM_STD:
3228 curproxy->options2 |= cfg_opts2[optnum].val;
3229 break;
3230 case KWM_NO:
3231 curproxy->no_options2 |= cfg_opts2[optnum].val;
3232 break;
3233 case KWM_DEF: /* already cleared */
3234 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003235 }
Willy Tarreau93893792009-07-23 13:19:11 +02003236 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003237 }
3238 }
3239
Willy Tarreau3842f002009-06-14 11:39:52 +02003240 if (kwm != KWM_STD) {
3241 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003242 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003245 }
3246
Emeric Brun3a058f32009-06-30 18:26:00 +02003247 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003249 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003251 if (*(args[2]) != '\0') {
3252 if (!strcmp(args[2], "clf")) {
3253 curproxy->options2 |= PR_O2_CLFLOG;
3254 } else {
3255 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003258 }
3259 }
3260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 else if (!strcmp(args[1], "tcplog"))
3262 /* generate a detailed TCP log */
3263 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 else if (!strcmp(args[1], "tcpka")) {
3265 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003266 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003268
3269 if (curproxy->cap & PR_CAP_FE)
3270 curproxy->options |= PR_O_TCP_CLI_KA;
3271 if (curproxy->cap & PR_CAP_BE)
3272 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 }
3274 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003275 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_WARN;
3277
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003279 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003280 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003281 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003282 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003283 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003284 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003285 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 if (!*args[2]) { /* no argument */
3287 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3288 curproxy->check_len = strlen(DEF_CHECK_REQ);
3289 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003290 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 curproxy->check_req = (char *)malloc(reqlen);
3292 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003293 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003295 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if (*args[4])
3297 reqlen += strlen(args[4]);
3298 else
3299 reqlen += strlen("HTTP/1.0");
3300
3301 curproxy->check_req = (char *)malloc(reqlen);
3302 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003303 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003305 }
3306 else if (!strcmp(args[1], "ssl-hello-chk")) {
3307 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003308 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003310
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 Tarreauf3c69202006-07-09 16:42:34 +02003313 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003314 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003315 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003316 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003317 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
Willy Tarreau23677902007-05-08 23:50:35 +02003319 else if (!strcmp(args[1], "smtpchk")) {
3320 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003321 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003322 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003323 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003324 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003325 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003326 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003327 curproxy->options |= PR_O_SMTP_CHK;
3328
3329 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3330 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3331 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3332 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3333 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3334 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3335 curproxy->check_req = (char *)malloc(reqlen);
3336 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3337 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3338 } else {
3339 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3340 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3341 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3342 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3343 }
3344 }
3345 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003346 else if (!strcmp(args[1], "mysql-check")) {
3347 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003348 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3349 err_code |= ERR_WARN;
3350
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003351 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003352 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003353 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003354 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003355 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003356 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003357 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003358
3359 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3360 * const char mysql40_client_auth_pkt[] = {
3361 * "\x0e\x00\x00" // packet length
3362 * "\x01" // packet number
3363 * "\x00\x00" // client capabilities
3364 * "\x00\x00\x01" // max packet
3365 * "haproxy\x00" // username (null terminated string)
3366 * "\x00" // filler (always 0x00)
3367 * "\x01\x00\x00" // packet length
3368 * "\x00" // packet number
3369 * "\x01" // COM_QUIT command
3370 * };
3371 */
3372
3373 if (*(args[2])) {
3374 int cur_arg = 2;
3375
3376 while (*(args[cur_arg])) {
3377 if (strcmp(args[cur_arg], "user") == 0) {
3378 char *mysqluser;
3379 int packetlen, reqlen, userlen;
3380
3381 /* suboption header - needs additional argument for it */
3382 if (*(args[cur_arg+1]) == 0) {
3383 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3384 file, linenum, args[0], args[1], args[cur_arg]);
3385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388 mysqluser = args[cur_arg + 1];
3389 userlen = strlen(mysqluser);
3390 packetlen = userlen + 7;
3391 reqlen = packetlen + 9;
3392
3393 free(curproxy->check_req);
3394 curproxy->check_req = (char *)calloc(1, reqlen);
3395 curproxy->check_len = reqlen;
3396
3397 snprintf(curproxy->check_req, 4, "%c%c%c",
3398 ((unsigned char) packetlen & 0xff),
3399 ((unsigned char) (packetlen >> 8) & 0xff),
3400 ((unsigned char) (packetlen >> 16) & 0xff));
3401
3402 curproxy->check_req[3] = 1;
3403 curproxy->check_req[8] = 1;
3404 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3405 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3406 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3407 cur_arg += 2;
3408 } else {
3409 /* unknown suboption - catchall */
3410 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3411 file, linenum, args[0], args[1]);
3412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
3414 }
3415 } /* end while loop */
3416 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003417 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003418 else if (!strcmp(args[1], "ldap-check")) {
3419 /* use LDAP request to check servers' health */
3420 free(curproxy->check_req);
3421 curproxy->check_req = NULL;
3422 curproxy->options &= ~PR_O_HTTP_CHK;
3423 curproxy->options &= ~PR_O_SMTP_CHK;
3424 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3425 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3426 curproxy->options2 |= PR_O2_LDAP_CHK;
3427
3428 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3429 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3430 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3431 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003432 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003433 int cur_arg;
3434
3435 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3436 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003437 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003438
3439 curproxy->options |= PR_O_FWDFOR;
3440
3441 free(curproxy->fwdfor_hdr_name);
3442 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3443 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3444
3445 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3446 cur_arg = 2;
3447 while (*(args[cur_arg])) {
3448 if (!strcmp(args[cur_arg], "except")) {
3449 /* suboption except - needs additional argument for it */
3450 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3451 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3452 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003455 }
3456 /* flush useless bits */
3457 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003458 cur_arg += 2;
3459 } else if (!strcmp(args[cur_arg], "header")) {
3460 /* suboption header - needs additional argument for it */
3461 if (*(args[cur_arg+1]) == 0) {
3462 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3463 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003466 }
3467 free(curproxy->fwdfor_hdr_name);
3468 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3469 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3470 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003471 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003472 /* unknown suboption - catchall */
3473 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3474 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003477 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003478 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003479 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003480 else if (!strcmp(args[1], "originalto")) {
3481 int cur_arg;
3482
3483 /* insert x-original-to field, but not for the IP address listed as an except.
3484 * set default options (ie: bitfield, header name, etc)
3485 */
3486
3487 curproxy->options |= PR_O_ORGTO;
3488
3489 free(curproxy->orgto_hdr_name);
3490 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3491 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3492
3493 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3494 cur_arg = 2;
3495 while (*(args[cur_arg])) {
3496 if (!strcmp(args[cur_arg], "except")) {
3497 /* suboption except - needs additional argument for it */
3498 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3499 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3500 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003503 }
3504 /* flush useless bits */
3505 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3506 cur_arg += 2;
3507 } else if (!strcmp(args[cur_arg], "header")) {
3508 /* suboption header - needs additional argument for it */
3509 if (*(args[cur_arg+1]) == 0) {
3510 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3511 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003514 }
3515 free(curproxy->orgto_hdr_name);
3516 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3517 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3518 cur_arg += 2;
3519 } else {
3520 /* unknown suboption - catchall */
3521 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3522 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003525 }
3526 } /* end while loop */
3527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 else {
3529 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
Willy Tarreau93893792009-07-23 13:19:11 +02003533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003535 else if (!strcmp(args[0], "default_backend")) {
3536 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003538
3539 if (*(args[1]) == 0) {
3540 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003543 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003544 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003545 curproxy->defbe.name = strdup(args[1]);
3546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003550
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003551 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 /* enable reconnections to dispatch */
3555 curproxy->options |= PR_O_REDISP;
3556 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003557 else if (!strcmp(args[0], "http-check")) {
3558 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003560
3561 if (strcmp(args[1], "disable-on-404") == 0) {
3562 /* enable a graceful server shutdown on an HTTP 404 response */
3563 curproxy->options |= PR_O_DISABLE404;
3564 }
Willy Tarreauef781042010-01-27 11:53:01 +01003565 else if (strcmp(args[1], "send-state") == 0) {
3566 /* enable emission of the apparent state of a server in HTTP checks */
3567 curproxy->options2 |= PR_O2_CHK_SNDST;
3568 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003569 else if (strcmp(args[1], "expect") == 0) {
3570 const char *ptr_arg;
3571 int cur_arg;
3572
3573 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3574 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578
3579 cur_arg = 2;
3580 /* consider exclamation marks, sole or at the beginning of a word */
3581 while (*(ptr_arg = args[cur_arg])) {
3582 while (*ptr_arg == '!') {
3583 curproxy->options2 ^= PR_O2_EXP_INV;
3584 ptr_arg++;
3585 }
3586 if (*ptr_arg)
3587 break;
3588 cur_arg++;
3589 }
3590 /* now ptr_arg points to the beginning of a word past any possible
3591 * exclamation mark, and cur_arg is the argument which holds this word.
3592 */
3593 if (strcmp(ptr_arg, "status") == 0) {
3594 if (!*(args[cur_arg + 1])) {
3595 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3596 file, linenum, args[0], args[1], ptr_arg);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
3599 }
3600 curproxy->options2 |= PR_O2_EXP_STS;
3601 curproxy->expect_str = strdup(args[cur_arg + 1]);
3602 }
3603 else if (strcmp(ptr_arg, "string") == 0) {
3604 if (!*(args[cur_arg + 1])) {
3605 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3606 file, linenum, args[0], args[1], ptr_arg);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
3609 }
3610 curproxy->options2 |= PR_O2_EXP_STR;
3611 curproxy->expect_str = strdup(args[cur_arg + 1]);
3612 }
3613 else if (strcmp(ptr_arg, "rstatus") == 0) {
3614 if (!*(args[cur_arg + 1])) {
3615 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3616 file, linenum, args[0], args[1], ptr_arg);
3617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
3619 }
3620 curproxy->options2 |= PR_O2_EXP_RSTS;
3621 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3622 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3623 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3624 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
3627 }
3628 }
3629 else if (strcmp(ptr_arg, "rstring") == 0) {
3630 if (!*(args[cur_arg + 1])) {
3631 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3632 file, linenum, args[0], args[1], ptr_arg);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 curproxy->options2 |= PR_O2_EXP_RSTR;
3637 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3638 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3639 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3640 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
3643 }
3644 }
3645 else {
3646 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3647 file, linenum, args[0], args[1], ptr_arg);
3648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
3650 }
3651 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003652 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003653 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003656 }
3657 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003658 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003659 if (curproxy == &defproxy) {
3660 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003663 }
3664
Willy Tarreaub80c2302007-11-30 20:51:32 +01003665 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003667
3668 if (strcmp(args[1], "fail") == 0) {
3669 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003670 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003671 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3672 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003675 }
3676
Willy Tarreauef6494c2010-01-28 17:12:36 +01003677 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003678 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3679 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003682 }
3683 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3684 }
3685 else {
3686 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003689 }
3690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691#ifdef TPROXY
3692 else if (!strcmp(args[0], "transparent")) {
3693 /* enable transparent proxy connections */
3694 curproxy->options |= PR_O_TRANSP;
3695 }
3696#endif
3697 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003700
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 if (*(args[1]) == 0) {
3702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
3706 curproxy->maxconn = atol(args[1]);
3707 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003708 else if (!strcmp(args[0], "backlog")) { /* backlog */
3709 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003711
3712 if (*(args[1]) == 0) {
3713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003716 }
3717 curproxy->backlog = atol(args[1]);
3718 }
Willy Tarreau86034312006-12-29 00:10:33 +01003719 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003722
Willy Tarreau86034312006-12-29 00:10:33 +01003723 if (*(args[1]) == 0) {
3724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003727 }
3728 curproxy->fullconn = atol(args[1]);
3729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3731 if (*(args[1]) == 0) {
3732 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003736 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3737 if (err) {
3738 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3739 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003742 }
3743 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 }
3745 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003746 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 if (curproxy == &defproxy) {
3748 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003754
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 if (strchr(args[1], ':') == NULL) {
3756 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003760 sk = str2sa(args[1]);
3761 if (!sk) {
3762 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
3766 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
3768 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003772 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003773 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3774 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003779 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3780 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3781 err_code |= ERR_WARN;
3782
3783 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3784 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3785 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3786 }
3787 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3788 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3789 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3790 }
3791 else {
3792 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003797 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003799 char *rport, *raddr;
3800 short realport = 0;
3801 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003803 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003808 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810
3811 if (!*args[2]) {
3812 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3813 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003817
3818 err = invalid_char(args[1]);
3819 if (err) {
3820 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3821 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003824 }
3825
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003826 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003827 struct sockaddr_in *sk;
3828
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003829 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3830 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3831 err_code |= ERR_ALERT | ERR_ABORT;
3832 goto out;
3833 }
3834
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003835 /* the servers are linked backwards first */
3836 newsrv->next = curproxy->srv;
3837 curproxy->srv = newsrv;
3838 newsrv->proxy = curproxy;
3839 newsrv->conf.file = file;
3840 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003842 LIST_INIT(&newsrv->pendconns);
3843 do_check = 0;
3844 newsrv->state = SRV_RUNNING; /* early server setup */
3845 newsrv->last_change = now.tv_sec;
3846 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003848 /* several ways to check the port component :
3849 * - IP => port=+0, relative
3850 * - IP: => port=+0, relative
3851 * - IP:N => port=N, absolute
3852 * - IP:+N => port=+N, relative
3853 * - IP:-N => port=-N, relative
3854 */
3855 raddr = strdup(args[2]);
3856 rport = strchr(raddr, ':');
3857 if (rport) {
3858 *rport++ = 0;
3859 realport = atol(rport);
3860 if (!isdigit((unsigned char)*rport))
3861 newsrv->state |= SRV_MAPPORTS;
3862 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003864
Willy Tarreaud5191e72010-02-09 20:50:45 +01003865 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003866 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003867 if (!sk) {
3868 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
3871 }
3872 newsrv->addr = *sk;
3873 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003874
3875 newsrv->check_port = curproxy->defsrv.check_port;
3876 newsrv->inter = curproxy->defsrv.inter;
3877 newsrv->fastinter = curproxy->defsrv.fastinter;
3878 newsrv->downinter = curproxy->defsrv.downinter;
3879 newsrv->rise = curproxy->defsrv.rise;
3880 newsrv->fall = curproxy->defsrv.fall;
3881 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3882 newsrv->minconn = curproxy->defsrv.minconn;
3883 newsrv->maxconn = curproxy->defsrv.maxconn;
3884 newsrv->slowstart = curproxy->defsrv.slowstart;
3885 newsrv->onerror = curproxy->defsrv.onerror;
3886 newsrv->consecutive_errors_limit
3887 = curproxy->defsrv.consecutive_errors_limit;
3888 newsrv->uweight = newsrv->iweight
3889 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003891 newsrv->curfd = -1; /* no health-check in progress */
3892 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003894 cur_arg = 3;
3895 } else {
3896 newsrv = &curproxy->defsrv;
3897 cur_arg = 1;
3898 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003899
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003901 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003902 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003903
3904 if (!*args[cur_arg + 1]) {
3905 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3906 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003909 }
3910
3911 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003912 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003913
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003914 if (newsrv->puid <= 0) {
3915 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003916 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003919 }
3920
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003921 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3922 if (node) {
3923 struct server *target = container_of(node, struct server, conf.id);
3924 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3925 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003930 cur_arg += 2;
3931 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003932 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 newsrv->cookie = strdup(args[cur_arg + 1]);
3934 newsrv->cklen = strlen(args[cur_arg + 1]);
3935 cur_arg += 2;
3936 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003937 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003938 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3939 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3940 cur_arg += 2;
3941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003943 if (!*args[cur_arg + 1]) {
3944 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3945 file, linenum, args[cur_arg]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003951 if (newsrv->rise <= 0) {
3952 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3953 file, linenum, args[cur_arg]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
3956 }
3957
Willy Tarreau96839092010-03-29 10:02:24 +02003958 if (newsrv->health)
3959 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 cur_arg += 2;
3961 }
3962 else if (!strcmp(args[cur_arg], "fall")) {
3963 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003964
3965 if (!*args[cur_arg + 1]) {
3966 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3967 file, linenum, args[cur_arg]);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
3971
3972 if (newsrv->fall <= 0) {
3973 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3974 file, linenum, args[cur_arg]);
3975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
3977 }
3978
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 cur_arg += 2;
3980 }
3981 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003982 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3983 if (err) {
3984 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3985 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003988 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003989 if (val <= 0) {
3990 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3991 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003994 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003995 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 cur_arg += 2;
3997 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003998 else if (!strcmp(args[cur_arg], "fastinter")) {
3999 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4000 if (err) {
4001 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4002 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004005 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004006 if (val <= 0) {
4007 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4008 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004011 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004012 newsrv->fastinter = val;
4013 cur_arg += 2;
4014 }
4015 else if (!strcmp(args[cur_arg], "downinter")) {
4016 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4017 if (err) {
4018 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4019 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004022 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004023 if (val <= 0) {
4024 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4025 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004028 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004029 newsrv->downinter = val;
4030 cur_arg += 2;
4031 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004032 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004033 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4034 if (!sk) {
4035 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004040 cur_arg += 2;
4041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 else if (!strcmp(args[cur_arg], "port")) {
4043 newsrv->check_port = atol(args[cur_arg + 1]);
4044 cur_arg += 2;
4045 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004046 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 newsrv->state |= SRV_BACKUP;
4048 cur_arg ++;
4049 }
4050 else if (!strcmp(args[cur_arg], "weight")) {
4051 int w;
4052 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004053 if (w < 0 || w > 256) {
4054 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004059 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 cur_arg += 2;
4061 }
4062 else if (!strcmp(args[cur_arg], "minconn")) {
4063 newsrv->minconn = atol(args[cur_arg + 1]);
4064 cur_arg += 2;
4065 }
4066 else if (!strcmp(args[cur_arg], "maxconn")) {
4067 newsrv->maxconn = atol(args[cur_arg + 1]);
4068 cur_arg += 2;
4069 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004070 else if (!strcmp(args[cur_arg], "maxqueue")) {
4071 newsrv->maxqueue = atol(args[cur_arg + 1]);
4072 cur_arg += 2;
4073 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004074 else if (!strcmp(args[cur_arg], "slowstart")) {
4075 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004076 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004077 if (err) {
4078 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4079 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004082 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004083 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004084 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4085 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004088 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004089 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004090 cur_arg += 2;
4091 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004093
4094 if (!*args[cur_arg + 1]) {
4095 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4096 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004099 }
4100
4101 newsrv->trackit = strdup(args[cur_arg + 1]);
4102
4103 cur_arg += 2;
4104 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004105 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106 global.maxsock++;
4107 do_check = 1;
4108 cur_arg += 1;
4109 }
Willy Tarreau96839092010-03-29 10:02:24 +02004110 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4111 newsrv->state |= SRV_MAINTAIN;
4112 newsrv->state &= ~SRV_RUNNING;
4113 newsrv->health = 0;
4114 cur_arg += 1;
4115 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004117 if (!strcmp(args[cur_arg + 1], "none"))
4118 newsrv->observe = HANA_OBS_NONE;
4119 else if (!strcmp(args[cur_arg + 1], "layer4"))
4120 newsrv->observe = HANA_OBS_LAYER4;
4121 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4122 if (curproxy->mode != PR_MODE_HTTP) {
4123 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4124 file, linenum, args[cur_arg + 1]);
4125 err_code |= ERR_ALERT;
4126 }
4127 newsrv->observe = HANA_OBS_LAYER7;
4128 }
4129 else {
4130 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004131 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004132 file, linenum, args[cur_arg], args[cur_arg + 1]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136
4137 cur_arg += 2;
4138 }
4139 else if (!strcmp(args[cur_arg], "on-error")) {
4140 if (!strcmp(args[cur_arg + 1], "fastinter"))
4141 newsrv->onerror = HANA_ONERR_FASTINTER;
4142 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4143 newsrv->onerror = HANA_ONERR_FAILCHK;
4144 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4145 newsrv->onerror = HANA_ONERR_SUDDTH;
4146 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4147 newsrv->onerror = HANA_ONERR_MARKDWN;
4148 else {
4149 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004150 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004151 file, linenum, args[cur_arg], args[cur_arg + 1]);
4152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
4154 }
4155
4156 cur_arg += 2;
4157 }
4158 else if (!strcmp(args[cur_arg], "error-limit")) {
4159 if (!*args[cur_arg + 1]) {
4160 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4161 file, linenum, args[cur_arg]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165
4166 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4167
4168 if (newsrv->consecutive_errors_limit <= 0) {
4169 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4170 file, linenum, args[cur_arg]);
4171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
4173 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004174 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004175 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004176 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004177 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004178 struct sockaddr_in *sk;
4179
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004181#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004182 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004183 file, linenum, "source", "usesrc");
4184#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004185 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004187#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 }
4191 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004192 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4193 if (!sk) {
4194 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
4197 }
4198 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004199
4200 if (port_low != port_high) {
4201 int i;
4202 if (port_low <= 0 || port_low > 65535 ||
4203 port_high <= 0 || port_high > 65535 ||
4204 port_low > port_high) {
4205 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4206 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004209 }
4210 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4211 for (i = 0; i < newsrv->sport_range->size; i++)
4212 newsrv->sport_range->ports[i] = port_low + i;
4213 }
4214
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004216 while (*(args[cur_arg])) {
4217 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004218#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4219#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004220 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4221 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4222 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004225 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004226#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004227 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004228 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004229 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004232 }
4233 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004234 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004235 newsrv->state |= SRV_TPROXY_CLI;
4236 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004237 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004238 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004239 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4240 char *name, *end;
4241
4242 name = args[cur_arg+1] + 7;
4243 while (isspace(*name))
4244 name++;
4245
4246 end = name;
4247 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4248 end++;
4249
4250 newsrv->state &= ~SRV_TPROXY_MASK;
4251 newsrv->state |= SRV_TPROXY_DYN;
4252 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4253 newsrv->bind_hdr_len = end - name;
4254 memcpy(newsrv->bind_hdr_name, name, end - name);
4255 newsrv->bind_hdr_name[end-name] = '\0';
4256 newsrv->bind_hdr_occ = -1;
4257
4258 /* now look for an occurrence number */
4259 while (isspace(*end))
4260 end++;
4261 if (*end == ',') {
4262 end++;
4263 name = end;
4264 if (*end == '-')
4265 end++;
4266 while (isdigit(*end))
4267 end++;
4268 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4269 }
4270
4271 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4272 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4273 " occurrences values smaller than %d.\n",
4274 file, linenum, MAX_HDR_HISTORY);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004278 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004279 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4280 if (!sk) {
4281 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
4285 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004286 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004287 }
4288 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004289#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004290 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004291#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004292 cur_arg += 2;
4293 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004294#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004295 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004296 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004299#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4300 } /* "usesrc" */
4301
4302 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4303#ifdef SO_BINDTODEVICE
4304 if (!*args[cur_arg + 1]) {
4305 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004309 }
4310 if (newsrv->iface_name)
4311 free(newsrv->iface_name);
4312
4313 newsrv->iface_name = strdup(args[cur_arg + 1]);
4314 newsrv->iface_len = strlen(newsrv->iface_name);
4315 global.last_checks |= LSTCHK_NETADM;
4316#else
4317 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4318 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004321#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004322 cur_arg += 2;
4323 continue;
4324 }
4325 /* this keyword in not an option of "source" */
4326 break;
4327 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004329 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004330 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4331 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004336 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004337 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 +01004338 file, linenum, newsrv->id);
4339 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004340 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 +01004341 file, linenum);
4342
Willy Tarreau93893792009-07-23 13:19:11 +02004343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 }
4346 }
4347
4348 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004349 if (newsrv->trackit) {
4350 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4351 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004352 err_code |= ERR_ALERT | ERR_FATAL;
4353 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004354 }
4355
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004356 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4357 newsrv->check_port = newsrv->check_addr.sin_port;
4358
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4360 newsrv->check_port = realport; /* by default */
4361 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004362 /* not yet valid, because no port was set on
4363 * the server either. We'll check if we have
4364 * a known port on the first listener.
4365 */
4366 struct listener *l;
4367 l = curproxy->listen;
4368 if (l) {
4369 int port;
4370 port = (l->addr.ss_family == AF_INET6)
4371 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4372 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4373 newsrv->check_port = port;
4374 }
4375 }
4376 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4378 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004382
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004383 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004384 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004385 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
4388 }
4389
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004390 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 newsrv->state |= SRV_CHECKED;
4392 }
4393
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004394 if (!defsrv) {
4395 if (newsrv->state & SRV_BACKUP)
4396 curproxy->srv_bck++;
4397 else
4398 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004399
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004400 newsrv->prev_state = newsrv->state;
4401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 }
4403 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004404 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 int facility;
4406
4407 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4408 curproxy->logfac1 = global.logfac1;
4409 curproxy->logsrv1 = global.logsrv1;
4410 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004411 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 curproxy->logfac2 = global.logfac2;
4413 curproxy->logsrv2 = global.logsrv2;
4414 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004415 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 }
4417 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004418 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419
4420 facility = get_log_facility(args[2]);
4421 if (facility < 0) {
4422 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4423 exit(1);
4424 }
4425
4426 level = 7; /* max syslog level = debug */
4427 if (*(args[3])) {
4428 level = get_log_level(args[3]);
4429 if (level < 0) {
4430 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4431 exit(1);
4432 }
4433 }
4434
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004435 minlvl = 0; /* limit syslog level to this level (emerg) */
4436 if (*(args[4])) {
4437 minlvl = get_log_level(args[4]);
4438 if (level < 0) {
4439 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4440 exit(1);
4441 }
4442 }
4443
Robert Tsai81ae1952007-12-05 10:47:29 +01004444 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004445 struct sockaddr_un *sk = str2sun(args[1]);
4446 if (!sk) {
4447 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4448 args[1], (int)sizeof(sk->sun_path) - 1);
4449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
4451 }
4452 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004453 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004454 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004455 struct sockaddr_in *sk = str2sa(args[1]);
4456 if (!sk) {
4457 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
4460 }
4461 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004462 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004463 if (!logsrv.u.in.sin_port) {
4464 logsrv.u.in.sin_port =
4465 htons(SYSLOG_PORT);
4466 }
4467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468
4469 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004470 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 curproxy->logfac1 = facility;
4472 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004473 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 }
4475 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004476 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 curproxy->logfac2 = facility;
4478 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004479 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 }
4481 else {
4482 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 }
4486 }
4487 else {
4488 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4489 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 }
4493 }
4494 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004495 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004496 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004497
Willy Tarreau977b8e42006-12-29 14:19:17 +01004498 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004500
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004502 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4503 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004507
4508 /* we must first clear any optional default setting */
4509 curproxy->options &= ~PR_O_TPXY_MASK;
4510 free(curproxy->iface_name);
4511 curproxy->iface_name = NULL;
4512 curproxy->iface_len = 0;
4513
Willy Tarreaud5191e72010-02-09 20:50:45 +01004514 sk = str2sa(args[1]);
4515 if (!sk) {
4516 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
4519 }
4520 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004522
4523 cur_arg = 2;
4524 while (*(args[cur_arg])) {
4525 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004526#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4527#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004528 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4529 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4530 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004533 }
4534#endif
4535 if (!*args[cur_arg + 1]) {
4536 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4537 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004540 }
4541
4542 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004543 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004544 curproxy->options |= PR_O_TPXY_CLI;
4545 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004546 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004547 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004548 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4549 char *name, *end;
4550
4551 name = args[cur_arg+1] + 7;
4552 while (isspace(*name))
4553 name++;
4554
4555 end = name;
4556 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4557 end++;
4558
4559 curproxy->options &= ~PR_O_TPXY_MASK;
4560 curproxy->options |= PR_O_TPXY_DYN;
4561 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4562 curproxy->bind_hdr_len = end - name;
4563 memcpy(curproxy->bind_hdr_name, name, end - name);
4564 curproxy->bind_hdr_name[end-name] = '\0';
4565 curproxy->bind_hdr_occ = -1;
4566
4567 /* now look for an occurrence number */
4568 while (isspace(*end))
4569 end++;
4570 if (*end == ',') {
4571 end++;
4572 name = end;
4573 if (*end == '-')
4574 end++;
4575 while (isdigit(*end))
4576 end++;
4577 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4578 }
4579
4580 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4581 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4582 " occurrences values smaller than %d.\n",
4583 file, linenum, MAX_HDR_HISTORY);
4584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
4586 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004587 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004588 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4589 if (!sk) {
4590 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
4593 }
4594 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004595 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004596 }
4597 global.last_checks |= LSTCHK_NETADM;
4598#if !defined(CONFIG_HAP_LINUX_TPROXY)
4599 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004600#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004601#else /* no TPROXY support */
4602 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004603 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004606#endif
4607 cur_arg += 2;
4608 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004609 }
4610
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004611 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4612#ifdef SO_BINDTODEVICE
4613 if (!*args[cur_arg + 1]) {
4614 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4615 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004618 }
4619 if (curproxy->iface_name)
4620 free(curproxy->iface_name);
4621
4622 curproxy->iface_name = strdup(args[cur_arg + 1]);
4623 curproxy->iface_len = strlen(curproxy->iface_name);
4624 global.last_checks |= LSTCHK_NETADM;
4625#else
4626 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4627 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004630#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631 cur_arg += 2;
4632 continue;
4633 }
4634 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4635 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004640 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4641 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4642 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004647 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4649 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004653
4654 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4655 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004656 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004657 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
4660 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004661 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4662 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004663 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004664 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 }
4667 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004668 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4669 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004670 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004671 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 }
4674 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004675 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4676 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004677 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004678 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 }
4681 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004682 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4683 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004684 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004685 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004688 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004689 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4690 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004691 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004692 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004693 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004694 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004695 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004696 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4697 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004698 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004699 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004700 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004701 }
4702 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004703 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4704 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004705 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004706 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004707 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004709 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004710 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4712 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004716
4717 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4718 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004719 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004720 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 }
4723 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004724 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4725 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004726 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004727 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
4730 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004731 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4732 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004733 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004734 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 }
4737 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004738 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4739 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004740 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004741 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004745 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4746 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004747 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004748 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004751 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4753 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004754 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004755 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004756 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004759 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004760
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 if (curproxy == &defproxy) {
4762 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004766 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004767 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 if (*(args[1]) == 0) {
4770 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004774
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004775 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4776 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4777 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4778 file, linenum, args[0]);
4779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
4781 }
4782 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4783 }
4784 else if (*args[2]) {
4785 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4786 file, linenum, args[0], args[2]);
4787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
4790
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004791 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004792 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004793 wl->s = strdup(args[1]);
4794 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004795 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 }
4797 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004798 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4800 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004804
Willy Tarreauade5ec42010-01-28 19:33:49 +01004805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4806 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004807 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810 }
4811 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4813 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004814 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 }
4818 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4820 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004821 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004822 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
4825 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4828 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 }
4832
Willy Tarreauade5ec42010-01-28 19:33:49 +01004833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4834 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004835 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 }
4839 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4841 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004842 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004843 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 }
4846 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4848 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004849 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004850 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 }
4853 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004854 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004855
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 if (curproxy == &defproxy) {
4857 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004861 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 if (*(args[1]) == 0) {
4865 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 }
4869
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004870 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4871 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4872 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4873 file, linenum, args[0]);
4874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
4876 }
4877 err_code |= warnif_cond_requires_req(cond, file, linenum);
4878 }
4879 else if (*args[2]) {
4880 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4881 file, linenum, args[0], args[2]);
4882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
4884 }
4885
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004886 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004887 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004888 wl->s = strdup(args[1]);
4889 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 }
4891 else if (!strcmp(args[0], "errorloc") ||
4892 !strcmp(args[0], "errorloc302") ||
4893 !strcmp(args[0], "errorloc303")) { /* error location */
4894 int errnum, errlen;
4895 char *err;
4896
Willy Tarreau977b8e42006-12-29 14:19:17 +01004897 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004899
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004901 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 }
4905
4906 errnum = atol(args[1]);
4907 if (!strcmp(args[0], "errorloc303")) {
4908 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4909 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4910 } else {
4911 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4912 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4913 }
4914
Willy Tarreau0f772532006-12-23 20:51:41 +01004915 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4916 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004917 chunk_destroy(&curproxy->errmsg[rc]);
4918 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004919 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004922
4923 if (rc >= HTTP_ERR_SIZE) {
4924 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4925 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 free(err);
4927 }
4928 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004929 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4930 int errnum, errlen, fd;
4931 char *err;
4932 struct stat stat;
4933
4934 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004935 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004936
4937 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004938 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004941 }
4942
4943 fd = open(args[2], O_RDONLY);
4944 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4945 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4946 file, linenum, args[2], args[1]);
4947 if (fd >= 0)
4948 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004951 }
4952
Willy Tarreau27a674e2009-08-17 07:23:33 +02004953 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004954 errlen = stat.st_size;
4955 } else {
4956 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004957 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004958 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004959 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004960 }
4961
4962 err = malloc(errlen); /* malloc() must succeed during parsing */
4963 errnum = read(fd, err, errlen);
4964 if (errnum != errlen) {
4965 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4966 file, linenum, args[2], args[1]);
4967 close(fd);
4968 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004971 }
4972 close(fd);
4973
4974 errnum = atol(args[1]);
4975 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4976 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004977 chunk_destroy(&curproxy->errmsg[rc]);
4978 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004979 break;
4980 }
4981 }
4982
4983 if (rc >= HTTP_ERR_SIZE) {
4984 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4985 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004987 free(err);
4988 }
4989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004991 struct cfg_kw_list *kwl;
4992 int index;
4993
4994 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4995 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4996 if (kwl->kw[index].section != CFG_LISTEN)
4997 continue;
4998 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4999 /* prepare error message just in case */
5000 snprintf(trash, sizeof(trash),
5001 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005002 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5003 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005004 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005007 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005008 else if (rc > 0) {
5009 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005010 err_code |= ERR_WARN;
5011 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005012 }
Willy Tarreau93893792009-07-23 13:19:11 +02005013 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005014 }
5015 }
5016 }
5017
Willy Tarreau6daf3432008-01-22 16:44:08 +01005018 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 }
Willy Tarreau93893792009-07-23 13:19:11 +02005022 out:
5023 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024}
5025
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005026int
5027cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5028{
5029
5030 int err_code = 0;
5031 const char *err;
5032
5033 if (!strcmp(args[0], "userlist")) { /* new userlist */
5034 struct userlist *newul;
5035
5036 if (!*args[1]) {
5037 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5038 file, linenum, args[0]);
5039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
5042
5043 err = invalid_char(args[1]);
5044 if (err) {
5045 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5046 file, linenum, *err, args[0], args[1]);
5047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
5049 }
5050
5051 for (newul = userlist; newul; newul = newul->next)
5052 if (!strcmp(newul->name, args[1])) {
5053 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5054 file, linenum, args[1]);
5055 err_code |= ERR_WARN;
5056 goto out;
5057 }
5058
5059 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5060 if (!newul) {
5061 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5062 err_code |= ERR_ALERT | ERR_ABORT;
5063 goto out;
5064 }
5065
5066 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5067 newul->name = strdup(args[1]);
5068
5069 if (!newul->groupusers | !newul->name) {
5070 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5071 err_code |= ERR_ALERT | ERR_ABORT;
5072 goto out;
5073 }
5074
5075 newul->next = userlist;
5076 userlist = newul;
5077
5078 } else if (!strcmp(args[0], "group")) { /* new group */
5079 int cur_arg, i;
5080 const char *err;
5081
5082 if (!*args[1]) {
5083 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5084 file, linenum, args[0]);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
5088
5089 err = invalid_char(args[1]);
5090 if (err) {
5091 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5092 file, linenum, *err, args[0], args[1]);
5093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
5095 }
5096
5097 for(i = 0; i < userlist->grpcnt; i++)
5098 if (!strcmp(userlist->groups[i], args[1])) {
5099 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5100 file, linenum, args[1], userlist->name);
5101 err_code |= ERR_ALERT;
5102 goto out;
5103 }
5104
5105 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5106 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5107 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
5110 }
5111
5112 cur_arg = 2;
5113
5114 while (*args[cur_arg]) {
5115 if (!strcmp(args[cur_arg], "users")) {
5116 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5117 cur_arg += 2;
5118 continue;
5119 } else {
5120 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5121 file, linenum, args[0]);
5122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
5124 }
5125 }
5126
5127 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5128 } else if (!strcmp(args[0], "user")) { /* new user */
5129 struct auth_users *newuser;
5130 int cur_arg;
5131
5132 if (!*args[1]) {
5133 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5134 file, linenum, args[0]);
5135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
5137 }
5138
5139 for (newuser = userlist->users; newuser; newuser = newuser->next)
5140 if (!strcmp(newuser->user, args[1])) {
5141 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5142 file, linenum, args[1], userlist->name);
5143 err_code |= ERR_ALERT;
5144 goto out;
5145 }
5146
5147 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5148 if (!newuser) {
5149 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5150 err_code |= ERR_ALERT | ERR_ABORT;
5151 goto out;
5152 }
5153
5154 newuser->user = strdup(args[1]);
5155
5156 newuser->next = userlist->users;
5157 userlist->users = newuser;
5158
5159 cur_arg = 2;
5160
5161 while (*args[cur_arg]) {
5162 if (!strcmp(args[cur_arg], "password")) {
5163#ifndef CONFIG_HAP_CRYPT
5164 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5165 file, linenum);
5166 err_code |= ERR_ALERT;
5167#endif
5168 newuser->pass = strdup(args[cur_arg + 1]);
5169 cur_arg += 2;
5170 continue;
5171 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5172 newuser->pass = strdup(args[cur_arg + 1]);
5173 newuser->flags |= AU_O_INSECURE;
5174 cur_arg += 2;
5175 continue;
5176 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005177 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005178 cur_arg += 2;
5179 continue;
5180 } else {
5181 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5182 file, linenum, args[0]);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
5186 }
5187 } else {
5188 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5189 err_code |= ERR_ALERT | ERR_FATAL;
5190 }
5191
5192out:
5193 return err_code;
5194}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195
5196/*
5197 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005198 * Returns the error code, 0 if OK, or any combination of :
5199 * - ERR_ABORT: must abort ASAP
5200 * - ERR_FATAL: we can continue parsing but not start the service
5201 * - ERR_WARN: a warning has been emitted
5202 * - ERR_ALERT: an alert has been emitted
5203 * Only the two first ones can stop processing, the two others are just
5204 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005206int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005207{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005208 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 FILE *f;
5210 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005212 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 if ((f=fopen(file,"r")) == NULL)
5215 return -1;
5216
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005217 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005218 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005219 char *end;
5220 char *args[MAX_LINE_ARGS + 1];
5221 char *line = thisline;
5222
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 linenum++;
5224
5225 end = line + strlen(line);
5226
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005227 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5228 /* Check if we reached the limit and the last char is not \n.
5229 * Watch out for the last line without the terminating '\n'!
5230 */
5231 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005232 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005234 }
5235
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005237 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 line++;
5239
5240 arg = 0;
5241 args[arg] = line;
5242
5243 while (*line && arg < MAX_LINE_ARGS) {
5244 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5245 * C equivalent value. Other combinations left unchanged (eg: \1).
5246 */
5247 if (*line == '\\') {
5248 int skip = 0;
5249 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5250 *line = line[1];
5251 skip = 1;
5252 }
5253 else if (line[1] == 'r') {
5254 *line = '\r';
5255 skip = 1;
5256 }
5257 else if (line[1] == 'n') {
5258 *line = '\n';
5259 skip = 1;
5260 }
5261 else if (line[1] == 't') {
5262 *line = '\t';
5263 skip = 1;
5264 }
5265 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005266 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 unsigned char hex1, hex2;
5268 hex1 = toupper(line[2]) - '0';
5269 hex2 = toupper(line[3]) - '0';
5270 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5271 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5272 *line = (hex1<<4) + hex2;
5273 skip = 3;
5274 }
5275 else {
5276 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 }
5279 }
5280 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005281 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 end -= skip;
5283 }
5284 line++;
5285 }
5286 else if (*line == '#' || *line == '\n' || *line == '\r') {
5287 /* end of string, end of loop */
5288 *line = 0;
5289 break;
5290 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005291 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005293 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005294 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 line++;
5296 args[++arg] = line;
5297 }
5298 else {
5299 line++;
5300 }
5301 }
5302
5303 /* empty line */
5304 if (!**args)
5305 continue;
5306
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005307 if (*line) {
5308 /* we had to stop due to too many args.
5309 * Let's terminate the string, print the offending part then cut the
5310 * last arg.
5311 */
5312 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5313 line++;
5314 *line = '\0';
5315
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005316 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005317 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005318 err_code |= ERR_ALERT | ERR_FATAL;
5319 args[arg] = line;
5320 }
5321
Willy Tarreau540abe42007-05-02 20:50:16 +02005322 /* zero out remaining args and ensure that at least one entry
5323 * is zeroed out.
5324 */
5325 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 args[arg] = line;
5327 }
5328
Willy Tarreau3842f002009-06-14 11:39:52 +02005329 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005330 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005331 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005332 for (arg=0; *args[arg+1]; arg++)
5333 args[arg] = args[arg+1]; // shift args after inversion
5334 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005335 else if (!strcmp(args[0], "default")) {
5336 kwm = KWM_DEF;
5337 for (arg=0; *args[arg+1]; arg++)
5338 args[arg] = args[arg+1]; // shift args after inversion
5339 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005340
Willy Tarreau3842f002009-06-14 11:39:52 +02005341 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5342 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005343 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005344 }
5345
Willy Tarreau977b8e42006-12-29 14:19:17 +01005346 if (!strcmp(args[0], "listen") ||
5347 !strcmp(args[0], "frontend") ||
5348 !strcmp(args[0], "backend") ||
5349 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005350 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005352 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005353 cursection = strdup(args[0]);
5354 }
5355 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005357 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005358 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005359 }
5360 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005361 confsect = CFG_USERLIST;
5362 free(cursection);
5363 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005364 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005365 else if (!strcmp(args[0], "peers")) {
5366 confsect = CFG_PEERS;
5367 free(cursection);
5368 cursection = strdup(args[0]);
5369 }
5370
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 /* else it's a section keyword */
5372
5373 switch (confsect) {
5374 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005375 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 break;
5377 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005378 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005380 case CFG_USERLIST:
5381 err_code |= cfg_parse_users(file, linenum, args, kwm);
5382 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005383 case CFG_PEERS:
5384 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5385 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005387 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005388 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005390
5391 if (err_code & ERR_ABORT)
5392 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005394 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005395 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005397 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005398}
5399
Willy Tarreaubb925012009-07-23 13:36:36 +02005400/*
5401 * Returns the error code, 0 if OK, or any combination of :
5402 * - ERR_ABORT: must abort ASAP
5403 * - ERR_FATAL: we can continue parsing but not start the service
5404 * - ERR_WARN: a warning has been emitted
5405 * - ERR_ALERT: an alert has been emitted
5406 * Only the two first ones can stop processing, the two others are just
5407 * indicators.
5408 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005409int check_config_validity()
5410{
5411 int cfgerr = 0;
5412 struct proxy *curproxy = NULL;
5413 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005414 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005415 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005416 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417
5418 /*
5419 * Now, check for the integrity of all that we have collected.
5420 */
5421
5422 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005423 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005425 /* first, we will invert the proxy list order */
5426 curproxy = NULL;
5427 while (proxy) {
5428 struct proxy *next;
5429
5430 next = proxy->next;
5431 proxy->next = curproxy;
5432 curproxy = proxy;
5433 if (!next)
5434 break;
5435 proxy = next;
5436 }
5437
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005439 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 }
5443
5444 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005445 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005446 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005447 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005448 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005449 unsigned int next_id;
5450
5451 if (!curproxy->uuid) {
5452 /* proxy ID not set, use automatic numbering with first
5453 * spare entry starting with next_pxid.
5454 */
5455 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5456 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5457 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005458 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005459 next_pxid++;
5460
Willy Tarreau55ea7572007-06-17 19:56:27 +02005461
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005463 /* ensure we don't keep listeners uselessly bound */
5464 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465 curproxy = curproxy->next;
5466 continue;
5467 }
5468
Willy Tarreauff01a212009-03-15 13:46:16 +01005469 switch (curproxy->mode) {
5470 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005471 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005472 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005473 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5474 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005475 cfgerr++;
5476 }
5477
5478 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005479 Warning("config : servers will be ignored for %s '%s'.\n",
5480 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005481 break;
5482
5483 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005484 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005485 break;
5486
5487 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005488 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005489 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005490 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5491 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005492 cfgerr++;
5493 }
5494 break;
5495 }
5496
5497 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005498 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5499 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 cfgerr++;
5501 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005502
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005503 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005504 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005505 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005506 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5507 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005508 cfgerr++;
5509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005511 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005512 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5513 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005514 cfgerr++;
5515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005517 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005518 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5519 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005520 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005521 }
5522 }
5523 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5524 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5525 /* If no LB algo is set in a backend, and we're not in
5526 * transparent mode, dispatch mode nor proxy mode, we
5527 * want to use balance roundrobin by default.
5528 */
5529 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5530 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531 }
5532 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005533
Willy Tarreau82936582007-11-30 15:20:09 +01005534 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5535 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005536 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5537 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005538 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005539 }
5540
Willy Tarreauef781042010-01-27 11:53:01 +01005541 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5542 curproxy->options &= ~PR_O2_CHK_SNDST;
5543 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5544 "send-state", proxy_type_str(curproxy), curproxy->id);
5545 err_code |= ERR_WARN;
5546 }
5547
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005548 /* if a default backend was specified, let's find it */
5549 if (curproxy->defbe.name) {
5550 struct proxy *target;
5551
Alex Williams96532db2009-11-01 21:27:13 -05005552 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005553 if (!target) {
5554 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5555 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005556 cfgerr++;
5557 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005558 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5559 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005560 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005561 } else {
5562 free(curproxy->defbe.name);
5563 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005564 /* we force the backend to be present on at least all of
5565 * the frontend's processes.
5566 */
5567 target->bind_proc = curproxy->bind_proc ?
5568 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 }
5570 }
5571
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005572 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005573 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5574 /* map jump target for ACT_SETBE in req_rep chain */
5575 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005576 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005577 struct proxy *target;
5578
Willy Tarreaua496b602006-12-17 23:15:24 +01005579 if (exp->action != ACT_SETBE)
5580 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005581
Alex Williams96532db2009-11-01 21:27:13 -05005582 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005583 if (!target) {
5584 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5585 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005586 cfgerr++;
5587 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005588 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5589 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005590 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005591 } else {
5592 free((void *)exp->replace);
5593 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005594 /* we force the backend to be present on at least all of
5595 * the frontend's processes.
5596 */
5597 target->bind_proc = curproxy->bind_proc ?
5598 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005599 }
5600 }
5601 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005602
5603 /* find the target proxy for 'use_backend' rules */
5604 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005605 struct proxy *target;
5606
Alex Williams96532db2009-11-01 21:27:13 -05005607 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005608
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005609 if (!target) {
5610 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5611 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005612 cfgerr++;
5613 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005614 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5615 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005616 cfgerr++;
5617 } else {
5618 free((void *)rule->be.name);
5619 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005620 /* we force the backend to be present on at least all of
5621 * the frontend's processes.
5622 */
5623 target->bind_proc = curproxy->bind_proc ?
5624 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005625 }
5626 }
5627
Emeric Brunb982a3d2010-01-04 15:45:53 +01005628 /* find the target table for 'stick' rules */
5629 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5630 struct proxy *target;
5631
Emeric Brun1d33b292010-01-04 15:47:17 +01005632 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5633 if (mrule->flags & STK_IS_STORE)
5634 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5635
Emeric Brunb982a3d2010-01-04 15:45:53 +01005636 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005637 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005638 else
5639 target = curproxy;
5640
5641 if (!target) {
5642 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5643 curproxy->id, mrule->table.name);
5644 cfgerr++;
5645 }
5646 else if (target->table.size == 0) {
5647 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5648 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5649 cfgerr++;
5650 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005651 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005652 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5653 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5654 cfgerr++;
5655 }
5656 else {
5657 free((void *)mrule->table.name);
5658 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005659 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005660 }
5661 }
5662
5663 /* find the target table for 'store response' rules */
5664 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5665 struct proxy *target;
5666
Emeric Brun1d33b292010-01-04 15:47:17 +01005667 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5668
Emeric Brunb982a3d2010-01-04 15:45:53 +01005669 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005670 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005671 else
5672 target = curproxy;
5673
5674 if (!target) {
5675 Alert("Proxy '%s': unable to find store table '%s'.\n",
5676 curproxy->id, mrule->table.name);
5677 cfgerr++;
5678 }
5679 else if (target->table.size == 0) {
5680 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5681 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5682 cfgerr++;
5683 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005684 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005685 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5686 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5687 cfgerr++;
5688 }
5689 else {
5690 free((void *)mrule->table.name);
5691 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005692 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005693 }
5694 }
5695
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005696 /* find the target table for 'tcp-request' layer 4 rules */
5697 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5698 struct proxy *target;
5699
Willy Tarreau56123282010-08-06 19:06:56 +02005700 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005701 continue;
5702
5703 if (trule->act_prm.trk_ctr.table.n)
5704 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5705 else
5706 target = curproxy;
5707
5708 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005709 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5710 curproxy->id, trule->act_prm.trk_ctr.table.n,
5711 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005712 cfgerr++;
5713 }
5714 else if (target->table.size == 0) {
5715 Alert("Proxy '%s': table '%s' used but not configured.\n",
5716 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5717 cfgerr++;
5718 }
5719 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005720 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 +02005721 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5722 cfgerr++;
5723 }
5724 else {
5725 free(trule->act_prm.trk_ctr.table.n);
5726 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005727 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005728 * to pass a list of counters to track and allocate them right here using
5729 * stktable_alloc_data_type().
5730 */
5731 }
5732 }
5733
Willy Tarreaud1f96522010-08-03 19:34:32 +02005734 /* find the target table for 'tcp-request' layer 6 rules */
5735 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5736 struct proxy *target;
5737
Willy Tarreau56123282010-08-06 19:06:56 +02005738 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005739 continue;
5740
5741 if (trule->act_prm.trk_ctr.table.n)
5742 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5743 else
5744 target = curproxy;
5745
5746 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005747 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5748 curproxy->id, trule->act_prm.trk_ctr.table.n,
5749 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005750 cfgerr++;
5751 }
5752 else if (target->table.size == 0) {
5753 Alert("Proxy '%s': table '%s' used but not configured.\n",
5754 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5755 cfgerr++;
5756 }
5757 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005758 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 +02005759 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5760 cfgerr++;
5761 }
5762 else {
5763 free(trule->act_prm.trk_ctr.table.n);
5764 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005765 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005766 * to pass a list of counters to track and allocate them right here using
5767 * stktable_alloc_data_type().
5768 */
5769 }
5770 }
5771
Emeric Brun32da3c42010-09-23 18:39:19 +02005772 if (curproxy->table.peers.name) {
5773 struct peers *curpeers = peers;
5774
5775 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5776 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5777 free((void *)curproxy->table.peers.name);
5778 curproxy->table.peers.p = peers;
5779 break;
5780 }
5781 }
5782
5783 if (!curpeers) {
5784 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5785 curproxy->id, curproxy->table.peers.name);
5786 cfgerr++;
5787 }
5788 else if (!curpeers->peers_fe) {
5789 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5790 curproxy->id, curpeers->id);
5791 cfgerr++;
5792 }
5793 }
5794
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005795 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5796 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005797 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5798 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5799 "proxy", curproxy->id);
5800 cfgerr++;
5801 goto out_uri_auth_compat;
5802 }
5803
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005804 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005805 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005806 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005807 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005808
Willy Tarreau95fa4692010-02-01 13:05:50 +01005809 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5810 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005811
5812 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005813 uri_auth_compat_req[i++] = "realm";
5814 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5815 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005816
Willy Tarreau95fa4692010-02-01 13:05:50 +01005817 uri_auth_compat_req[i++] = "unless";
5818 uri_auth_compat_req[i++] = "{";
5819 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5820 uri_auth_compat_req[i++] = "}";
5821 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005822
Willy Tarreau95fa4692010-02-01 13:05:50 +01005823 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5824 if (!req_acl) {
5825 cfgerr++;
5826 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005827 }
5828
Willy Tarreau95fa4692010-02-01 13:05:50 +01005829 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5830
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005831 if (curproxy->uri_auth->auth_realm) {
5832 free(curproxy->uri_auth->auth_realm);
5833 curproxy->uri_auth->auth_realm = NULL;
5834 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005835
5836 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005837 }
5838out_uri_auth_compat:
5839
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005840 cfgerr += acl_find_targets(curproxy);
5841
Willy Tarreau2738a142006-07-08 17:28:09 +02005842 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005843 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005844 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005845 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005846 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005847 " | While not properly invalid, you will certainly encounter various problems\n"
5848 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005849 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005850 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005851 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005852 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005853
Willy Tarreau1fa31262007-12-03 00:36:16 +01005854 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5855 * We must still support older configurations, so let's find out whether those
5856 * parameters have been set or must be copied from contimeouts.
5857 */
5858 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005859 if (!curproxy->timeout.tarpit ||
5860 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005861 /* tarpit timeout not set. We search in the following order:
5862 * default.tarpit, curr.connect, default.connect.
5863 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005864 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005865 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005866 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005867 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005868 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005869 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005870 }
5871 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005872 (!curproxy->timeout.queue ||
5873 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005874 /* queue timeout not set. We search in the following order:
5875 * default.queue, curr.connect, default.connect.
5876 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005877 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005878 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005879 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005880 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005881 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005882 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005883 }
5884 }
5885
Willy Tarreau07a54902010-03-29 18:33:29 +02005886 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005887 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5888 curproxy->check_req = (char *)malloc(curproxy->check_len);
5889 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005890 }
5891
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005892 /* The small pools required for the capture lists */
5893 if (curproxy->nb_req_cap)
5894 curproxy->req_cap_pool = create_pool("ptrcap",
5895 curproxy->nb_req_cap * sizeof(char *),
5896 MEM_F_SHARED);
5897 if (curproxy->nb_rsp_cap)
5898 curproxy->rsp_cap_pool = create_pool("ptrcap",
5899 curproxy->nb_rsp_cap * sizeof(char *),
5900 MEM_F_SHARED);
5901
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005902 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5903 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5904 MEM_F_SHARED);
5905
Willy Tarreau86034312006-12-29 00:10:33 +01005906 /* for backwards compatibility with "listen" instances, if
5907 * fullconn is not set but maxconn is set, then maxconn
5908 * is used.
5909 */
5910 if (!curproxy->fullconn)
5911 curproxy->fullconn = curproxy->maxconn;
5912
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 /* first, we will invert the servers list order */
5914 newsrv = NULL;
5915 while (curproxy->srv) {
5916 struct server *next;
5917
5918 next = curproxy->srv->next;
5919 curproxy->srv->next = newsrv;
5920 newsrv = curproxy->srv;
5921 if (!next)
5922 break;
5923 curproxy->srv = next;
5924 }
5925
Willy Tarreaudd701652010-05-25 23:03:02 +02005926 /* assign automatic UIDs to servers which don't have one yet */
5927 next_id = 1;
5928 newsrv = curproxy->srv;
5929 while (newsrv != NULL) {
5930 if (!newsrv->puid) {
5931 /* server ID not set, use automatic numbering with first
5932 * spare entry starting with next_svid.
5933 */
5934 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5935 newsrv->conf.id.key = newsrv->puid = next_id;
5936 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5937 }
5938 next_id++;
5939 newsrv = newsrv->next;
5940 }
5941
Willy Tarreau20697042007-11-15 23:26:18 +01005942 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005943 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005945 /* We have to initialize the server lookup mechanism depending
5946 * on what LB algorithm was choosen.
5947 */
5948
5949 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5950 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5951 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005952 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5953 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5954 init_server_map(curproxy);
5955 } else {
5956 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5957 fwrr_init_server_groups(curproxy);
5958 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005959 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005960
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005961 case BE_LB_KIND_LC:
5962 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005963 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005964 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005965
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005966 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005967 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5968 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5969 chash_init_server_tree(curproxy);
5970 } else {
5971 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5972 init_server_map(curproxy);
5973 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005974 break;
5975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976
5977 if (curproxy->options & PR_O_LOGASAP)
5978 curproxy->to_log &= ~LW_BYTES;
5979
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005980 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5981 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5982 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5983 proxy_type_str(curproxy), curproxy->id);
5984 err_code |= ERR_WARN;
5985 }
5986
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005987 if (curproxy->mode != PR_MODE_HTTP) {
5988 int optnum;
5989
5990 if (curproxy->options & PR_O_COOK_ANY) {
5991 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5992 proxy_type_str(curproxy), curproxy->id);
5993 err_code |= ERR_WARN;
5994 }
5995
5996 if (curproxy->uri_auth) {
5997 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5998 proxy_type_str(curproxy), curproxy->id);
5999 err_code |= ERR_WARN;
6000 curproxy->uri_auth = NULL;
6001 }
6002
6003 if (curproxy->options & PR_O_FWDFOR) {
6004 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6005 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6006 err_code |= ERR_WARN;
6007 curproxy->options &= ~PR_O_FWDFOR;
6008 }
6009
6010 if (curproxy->options & PR_O_ORGTO) {
6011 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6012 "originalto", proxy_type_str(curproxy), curproxy->id);
6013 err_code |= ERR_WARN;
6014 curproxy->options &= ~PR_O_ORGTO;
6015 }
6016
6017 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6018 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6019 (curproxy->cap & cfg_opts[optnum].cap) &&
6020 (curproxy->options & cfg_opts[optnum].val)) {
6021 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6022 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6023 err_code |= ERR_WARN;
6024 curproxy->options &= ~cfg_opts[optnum].val;
6025 }
6026 }
6027
6028 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6029 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6030 (curproxy->cap & cfg_opts2[optnum].cap) &&
6031 (curproxy->options2 & cfg_opts2[optnum].val)) {
6032 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6033 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6034 err_code |= ERR_WARN;
6035 curproxy->options2 &= ~cfg_opts2[optnum].val;
6036 }
6037 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006038
Willy Tarreauefa5f512010-03-30 20:13:29 +02006039#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006040 if (curproxy->bind_hdr_occ) {
6041 curproxy->bind_hdr_occ = 0;
6042 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6043 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6044 err_code |= ERR_WARN;
6045 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006046#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006047 }
6048
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006050 * ensure that we're not cross-dressing a TCP server into HTTP.
6051 */
6052 newsrv = curproxy->srv;
6053 while (newsrv != NULL) {
6054 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006055 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6056 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006057 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006058 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006059
Willy Tarreauefa5f512010-03-30 20:13:29 +02006060#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006061 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6062 newsrv->bind_hdr_occ = 0;
6063 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6064 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6065 err_code |= ERR_WARN;
6066 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006067#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006068 newsrv = newsrv->next;
6069 }
6070
6071 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072 * If this server supports a maxconn parameter, it needs a dedicated
6073 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006074 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075 */
6076 newsrv = curproxy->srv;
6077 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006078 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006079 /* Only 'minconn' was specified, or it was higher than or equal
6080 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6081 * this will avoid further useless expensive computations.
6082 */
6083 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006084 } else if (newsrv->maxconn && !newsrv->minconn) {
6085 /* minconn was not specified, so we set it to maxconn */
6086 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006087 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006088 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6089 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006090 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
6092
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006093 if (newsrv->trackit) {
6094 struct proxy *px;
6095 struct server *srv;
6096 char *pname, *sname;
6097
6098 pname = newsrv->trackit;
6099 sname = strrchr(pname, '/');
6100
6101 if (sname)
6102 *sname++ = '\0';
6103 else {
6104 sname = pname;
6105 pname = NULL;
6106 }
6107
6108 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006109 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006110 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006111 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6112 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006113 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006114 cfgerr++;
6115 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006116 }
6117 } else
6118 px = curproxy;
6119
6120 srv = findserver(px, sname);
6121 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006122 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6123 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006124 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006125 cfgerr++;
6126 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006127 }
6128
6129 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006130 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006131 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006132 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006133 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006134 cfgerr++;
6135 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006136 }
6137
6138 if (curproxy != px &&
6139 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006140 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006141 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006142 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006143 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006144 cfgerr++;
6145 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006146 }
6147
6148 newsrv->tracked = srv;
6149 newsrv->tracknext = srv->tracknext;
6150 srv->tracknext = newsrv;
6151
6152 free(newsrv->trackit);
6153 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006154 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 newsrv = newsrv->next;
6156 }
6157
Willy Tarreauc1a21672009-08-16 22:37:44 +02006158 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006159 curproxy->accept = frontend_accept;
6160
Willy Tarreauc1a21672009-08-16 22:37:44 +02006161 if (curproxy->tcp_req.inspect_delay ||
6162 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006163 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006164
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006165 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006166 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006167 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006168 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006169
6170 /* both TCP and HTTP must check switching rules */
6171 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6172 }
6173
6174 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006175 if (curproxy->tcp_req.inspect_delay ||
6176 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6177 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6178
Emeric Brun97679e72010-09-23 17:56:44 +02006179 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6180 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6181
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006182 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006183 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006184 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006185 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006186
6187 /* If the backend does requires RDP cookie persistence, we have to
6188 * enable the corresponding analyser.
6189 */
6190 if (curproxy->options2 & PR_O2_RDPC_PRST)
6191 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6192 }
6193
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006194 listener = NULL;
6195 while (curproxy->listen) {
6196 struct listener *next;
6197
6198 next = curproxy->listen->next;
6199 curproxy->listen->next = listener;
6200 listener = curproxy->listen;
6201
6202 if (!next)
6203 break;
6204
6205 curproxy->listen = next;
6206 }
6207
Willy Tarreaue6b98942007-10-29 01:09:36 +01006208 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006209 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006210 listener = curproxy->listen;
6211 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006212 if (!listener->luid) {
6213 /* listener ID not set, use automatic numbering with first
6214 * spare entry starting with next_luid.
6215 */
6216 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6217 listener->conf.id.key = listener->luid = next_id;
6218 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006219 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006220 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006221
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006222 /* enable separate counters */
6223 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6224 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6225 if (!listener->name) {
6226 sprintf(trash, "sock-%d", listener->luid);
6227 listener->name = strdup(trash);
6228 }
6229 }
6230
Willy Tarreaue6b98942007-10-29 01:09:36 +01006231 if (curproxy->options & PR_O_TCP_NOLING)
6232 listener->options |= LI_O_NOLINGER;
6233 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006234 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006235 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006236 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006237 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006238 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006239 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006240
Willy Tarreau8a956912010-10-15 14:27:08 +02006241 if (listener->options & LI_O_ACC_PROXY)
6242 listener->analysers |= AN_REQ_DECODE_PROXY;
6243
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006244 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6245 listener->options |= LI_O_TCP_RULES;
6246
Willy Tarreaude3041d2010-05-31 10:56:17 +02006247 if (curproxy->mon_mask.s_addr)
6248 listener->options |= LI_O_CHK_MONNET;
6249
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006250 /* smart accept mode is automatic in HTTP mode */
6251 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6252 (curproxy->mode == PR_MODE_HTTP &&
6253 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6254 listener->options |= LI_O_NOQUICKACK;
6255
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006256 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006257 listener = listener->next;
6258 }
6259
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 curproxy = curproxy->next;
6261 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006262
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006263 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6264 struct auth_users *curuser;
6265 int g;
6266
6267 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6268 unsigned int group_mask = 0;
6269 char *group = NULL;
6270
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006271 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006272 continue;
6273
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006274 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006275
6276 for (g = 0; g < curuserlist->grpcnt; g++)
6277 if (!strcmp(curuserlist->groups[g], group))
6278 break;
6279
6280 if (g == curuserlist->grpcnt) {
6281 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6282 curuserlist->name, group, curuser->user);
6283 err_code |= ERR_ALERT | ERR_FATAL;
6284 goto out;
6285 }
6286
6287 group_mask |= (1 << g);
6288 }
6289
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006290 free(curuser->u.groups);
6291 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006292 }
6293
6294 for (g = 0; g < curuserlist->grpcnt; g++) {
6295 char *user = NULL;
6296
6297 if (!curuserlist->groupusers[g])
6298 continue;
6299
6300 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6301 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6302 if (!strcmp(curuser->user, user))
6303 break;
6304
6305 if (!curuser) {
6306 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6307 curuserlist->name, user, curuserlist->groups[g]);
6308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
6310 }
6311
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006312 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006313 }
6314
6315 free(curuserlist->groupusers[g]);
6316 }
6317
6318 free(curuserlist->groupusers);
6319
6320#ifdef DEBUG_AUTH
6321 for (g = 0; g < curuserlist->grpcnt; g++) {
6322 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6323
6324 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6325 if (curuser->group_mask & (1 << g))
6326 fprintf(stderr, " %s", curuser->user);
6327 }
6328
6329 fprintf(stderr, "\n");
6330 }
6331#endif
6332
6333 }
6334
Willy Tarreau056f5682010-06-06 15:51:11 +02006335 /* initialize stick-tables on backend capable proxies. This must not
6336 * be done earlier because the data size may be discovered while parsing
6337 * other proxies.
6338 */
6339 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006340 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006341
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006342 /*
6343 * Recount currently required checks.
6344 */
6345
6346 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6347 int optnum;
6348
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006349 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6350 if (curproxy->options & cfg_opts[optnum].val)
6351 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006352
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006353 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6354 if (curproxy->options2 & cfg_opts2[optnum].val)
6355 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006356 }
6357
Willy Tarreaubb925012009-07-23 13:36:36 +02006358 if (cfgerr > 0)
6359 err_code |= ERR_ALERT | ERR_FATAL;
6360 out:
6361 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362}
6363
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006364/*
6365 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6366 * parsing sessions.
6367 */
6368void cfg_register_keywords(struct cfg_kw_list *kwl)
6369{
6370 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6371}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006373/*
6374 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6375 */
6376void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6377{
6378 LIST_DEL(&kwl->list);
6379 LIST_INIT(&kwl->list);
6380}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006381
6382/*
6383 * Local variables:
6384 * c-indent-level: 8
6385 * c-basic-offset: 8
6386 * End:
6387 */