blob: a67b348384bd1ad83aa4a336da415d17a173648b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010047#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
189 char *c, *next, *range, *dupstr;
190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
210 Alert("Socket path '%s' too long (max %d)\n", str, max_path_len);
211 goto fail;
212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200215 ss.ss_family = AF_UNIX;
216 if (global.unix_bind.prefix) {
217 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
218 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 }
Emeric Bruned760922010-10-22 17:59:25 +0200220 else {
221 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
222 }
223 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 }
225 else {
Emeric Bruned760922010-10-22 17:59:25 +0200226 /* 2) look for the addr/port delimiter, it's the last colon. */
227 if ((range = strrchr(str, ':')) == NULL) {
228 Alert("Missing port number: '%s'\n", str);
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231
232 *range++ = 0;
233
234 if (strrchr(str, ':') != NULL) {
235 /* IPv6 address contains ':' */
236 memset(&ss, 0, sizeof(ss));
237 ss.ss_family = AF_INET6;
238
239 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
240 Alert("Invalid server address: '%s'\n", str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Emeric Bruned760922010-10-22 17:59:25 +0200244 else {
245 memset(&ss, 0, sizeof(ss));
246 ss.ss_family = AF_INET;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Emeric Bruned760922010-10-22 17:59:25 +0200248 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
249 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
250 }
251 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
252 struct hostent *he;
253
254 if ((he = gethostbyname(str)) == NULL) {
255 Alert("Invalid server name: '%s'\n", str);
256 goto fail;
257 }
258 else
259 ((struct sockaddr_in *)&ss)->sin_addr =
260 *(struct in_addr *) *(he->h_addr_list);
261 }
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Emeric Bruned760922010-10-22 17:59:25 +0200264 /* 3) look for the port-end delimiter */
265 if ((c = strchr(range, '-')) != NULL) {
266 *c++ = 0;
267 end = atol(c);
268 }
269 else {
270 end = atol(range);
271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
Emeric Bruned760922010-10-22 17:59:25 +0200273 port = atol(range);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
Emeric Bruned760922010-10-22 17:59:25 +0200275 if (port < 1 || port > 65535) {
276 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
277 goto fail;
278 }
279
280 if (end < 1 || end > 65535) {
281 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
282 goto fail;
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 }
285
286 for (; port <= end; port++) {
287 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 l->next = curproxy->listen;
289 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
291 l->fd = -1;
292 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 l->state = LI_INIT;
294
Emeric Bruned760922010-10-22 17:59:25 +0200295 if(ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100297 tcpv4_add_listener(l);
298 }
Emeric Bruned760922010-10-22 17:59:25 +0200299 else if (ss.ss_family == AF_INET6) {
300 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
301 tcpv6_add_listener(l);
302 }
303 else {
304 l->perm.ux.gid = l->perm.ux.uid = -1;
305 l->perm.ux.mode = 0;
306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320/*
321 * Sends a warning if proxy <proxy> does not have at least one of the
322 * capabilities in <cap>. An optionnal <hint> may be added at the end
323 * of the warning to help the user. Returns 1 if a warning was emitted
324 * or 0 if the condition is valid.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100327{
328 char *msg;
329
330 switch (cap) {
331 case PR_CAP_BE: msg = "no backend"; break;
332 case PR_CAP_FE: msg = "no frontend"; break;
333 case PR_CAP_RS: msg = "no ruleset"; break;
334 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
335 default: msg = "not enough"; break;
336 }
337
338 if (!(proxy->cap & cap)) {
339 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100340 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100341 return 1;
342 }
343 return 0;
344}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345
Willy Tarreau61d18892009-03-31 10:49:21 +0200346/* Report a warning if a rule is placed after a 'block' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (!LIST_ISEMPTY(&proxy->block_cond)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
415 warnif_rule_after_reqadd(proxy, file, line, arg) ||
416 warnif_rule_after_redirect(proxy, file, line, arg) ||
417 warnif_rule_after_use_backend(proxy, file, line, arg);
418}
419
420/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100421int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200422{
423 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
424 warnif_rule_after_redirect(proxy, file, line, arg) ||
425 warnif_rule_after_use_backend(proxy, file, line, arg);
426}
427
428/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 return warnif_rule_after_redirect(proxy, file, line, arg) ||
432 warnif_rule_after_use_backend(proxy, file, line, arg);
433}
434
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100435/* Report it if a request ACL condition uses some response-only parameters. It
436 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
447 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100452/* Report it if a request ACL condition uses some request-only volatile parameters.
453 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
454 * Note that <cond> may be NULL and then will be ignored.
455 */
456static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
457{
458 struct acl *acl;
459
460 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
461 return 0;
462
463 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
464 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
465 file, line, acl ? acl->name : "(unknown)");
466 return ERR_WARN;
467}
468
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100469
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 * parse a line in a <global> section. Returns the error code, 0 if OK, or
472 * any combination of :
473 * - ERR_ABORT: must abort ASAP
474 * - ERR_FATAL: we can continue parsing but not start the service
475 * - ERR_WARN: a warning has been emitted
476 * - ERR_ALERT: an alert has been emitted
477 * Only the two first ones can stop processing, the two others are just
478 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200480int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481{
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483
484 if (!strcmp(args[0], "global")) { /* new section */
485 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 }
488 else if (!strcmp(args[0], "daemon")) {
489 global.mode |= MODE_DAEMON;
490 }
491 else if (!strcmp(args[0], "debug")) {
492 global.mode |= MODE_DEBUG;
493 }
494 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100495 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200497 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100498 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200499 }
500 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100501 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100504 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100506 else if (!strcmp(args[0], "nosplice")) {
507 global.tune.options &= ~GTUNE_USE_SPLICE;
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "quiet")) {
510 global.mode |= MODE_QUIET;
511 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200512 else if (!strcmp(args[0], "tune.maxpollevents")) {
513 if (global.tune.maxpollevents != 0) {
514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT;
516 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200517 }
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200522 }
523 global.tune.maxpollevents = atol(args[1]);
524 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100525 else if (!strcmp(args[0], "tune.maxaccept")) {
526 if (global.tune.maxaccept != 0) {
527 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200528 err_code |= ERR_ALERT;
529 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100530 }
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100535 }
536 global.tune.maxaccept = atol(args[1]);
537 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200538 else if (!strcmp(args[0], "tune.chksize")) {
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT | ERR_FATAL;
542 goto out;
543 }
544 global.tune.chksize = atol(args[1]);
545 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200546 else if (!strcmp(args[0], "tune.bufsize")) {
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.bufsize = atol(args[1]);
553 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
554 global.tune.maxrewrite = global.tune.bufsize / 2;
555 }
556 else if (!strcmp(args[0], "tune.maxrewrite")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.maxrewrite = atol(args[1]);
563 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
564 global.tune.maxrewrite = global.tune.bufsize / 2;
565 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100566 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
567 if (global.tune.client_rcvbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_rcvbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
580 if (global.tune.server_rcvbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_rcvbuf = atol(args[1]);
591 }
592 else if (!strcmp(args[0], "tune.sndbuf.client")) {
593 if (global.tune.client_sndbuf != 0) {
594 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT;
596 goto out;
597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.client_sndbuf = atol(args[1]);
604 }
605 else if (!strcmp(args[0], "tune.sndbuf.server")) {
606 if (global.tune.server_sndbuf != 0) {
607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT;
609 goto out;
610 }
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.server_sndbuf = atol(args[1]);
617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 else if (!strcmp(args[0], "uid")) {
619 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 global.uid = atol(args[1]);
630 }
631 else if (!strcmp(args[0], "gid")) {
632 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.gid = atol(args[1]);
643 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 /* user/group name handling */
645 else if (!strcmp(args[0], "user")) {
646 struct passwd *ha_user;
647 if (global.uid != 0) {
648 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 errno = 0;
653 ha_user = getpwnam(args[1]);
654 if (ha_user != NULL) {
655 global.uid = (int)ha_user->pw_uid;
656 }
657 else {
658 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 }
662 else if (!strcmp(args[0], "group")) {
663 struct group *ha_group;
664 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200665 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 errno = 0;
670 ha_group = getgrnam(args[1]);
671 if (ha_group != NULL) {
672 global.gid = (int)ha_group->gr_gid;
673 }
674 else {
675 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200677 }
678 }
679 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nbproc")) {
681 if (global.nbproc != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 global.nbproc = atol(args[1]);
692 }
693 else if (!strcmp(args[0], "maxconn")) {
694 if (global.maxconn != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.maxconn = atol(args[1]);
705#ifdef SYSTEM_MAXCONN
706 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
707 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
708 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711#endif /* SYSTEM_MAXCONN */
712 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100713 else if (!strcmp(args[0], "maxpipes")) {
714 if (global.maxpipes != 0) {
715 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200716 err_code |= ERR_ALERT;
717 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100718 }
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100723 }
724 global.maxpipes = atol(args[1]);
725 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 else if (!strcmp(args[0], "ulimit-n")) {
727 if (global.rlimit_nofile != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 global.rlimit_nofile = atol(args[1]);
738 }
739 else if (!strcmp(args[0], "chroot")) {
740 if (global.chroot != NULL) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.chroot = strdup(args[1]);
751 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200752 else if (!strcmp(args[0], "description")) {
753 int i, len=0;
754 char *d;
755
756 if (!*args[1]) {
757 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
758 file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762
763 for(i=1; *args[i]; i++)
764 len += strlen(args[i])+1;
765
766 if (global.desc)
767 free(global.desc);
768
769 global.desc = d = (char *)calloc(1, len);
770
771 d += sprintf(d, "%s", args[1]);
772 for(i=2; *args[i]; i++)
773 d += sprintf(d, " %s", args[i]);
774 }
775 else if (!strcmp(args[0], "node")) {
776 int i;
777 char c;
778
779 for (i=0; args[1][i]; i++) {
780 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100781 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
782 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200783 break;
784 }
785
786 if (!i || args[1][i]) {
787 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
788 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793
794 if (global.node)
795 free(global.node);
796
797 global.node = strdup(args[1]);
798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 else if (!strcmp(args[0], "pidfile")) {
800 if (global.pidfile != NULL) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 global.pidfile = strdup(args[1]);
811 }
Emeric Bruned760922010-10-22 17:59:25 +0200812 else if (!strcmp(args[0], "unix-bind")) {
813 int cur_arg = 1;
814 while (*(args[cur_arg])) {
815 if (!strcmp(args[cur_arg], "prefix")) {
816 if (global.unix_bind.prefix != NULL) {
817 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
818 err_code |= ERR_ALERT;
819 cur_arg += 2;
820 continue;
821 }
822
823 if (*(args[cur_arg+1]) == 0) {
824 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.unix_bind.prefix = strdup(args[cur_arg+1]);
829 cur_arg += 2;
830 continue;
831 }
832
833 if (!strcmp(args[cur_arg], "mode")) {
834
835 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
836 cur_arg += 2;
837 continue;
838 }
839
840 if (!strcmp(args[cur_arg], "uid")) {
841
842 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
843 cur_arg += 2;
844 continue;
845 }
846
847 if (!strcmp(args[cur_arg], "gid")) {
848
849 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
850 cur_arg += 2;
851 continue;
852 }
853
854 if (!strcmp(args[cur_arg], "user")) {
855 struct passwd *user;
856
857 user = getpwnam(args[cur_arg + 1]);
858 if (!user) {
859 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
860 file, linenum, args[0], args[cur_arg + 1 ]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864
865 global.unix_bind.ux.uid = user->pw_uid;
866 cur_arg += 2;
867 continue;
868 }
869
870 if (!strcmp(args[cur_arg], "group")) {
871 struct group *group;
872
873 group = getgrnam(args[cur_arg + 1]);
874 if (!group) {
875 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
876 file, linenum, args[0], args[cur_arg + 1 ]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880
881 global.unix_bind.ux.gid = group->gr_gid;
882 cur_arg += 2;
883 continue;
884 }
885
886 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
887 file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100893 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200894 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895
896 if (*(args[1]) == 0 || *(args[2]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901
902 facility = get_log_facility(args[2]);
903 if (facility < 0) {
904 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200905 err_code |= ERR_ALERT | ERR_FATAL;
906 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907 }
908
909 level = 7; /* max syslog level = debug */
910 if (*(args[3])) {
911 level = get_log_level(args[3]);
912 if (level < 0) {
913 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200914 err_code |= ERR_ALERT | ERR_FATAL;
915 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 }
917 }
918
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200919 minlvl = 0; /* limit syslog level to this level (emerg) */
920 if (*(args[4])) {
921 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200923 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
925 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 }
927 }
928
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100930 struct sockaddr_un *sk = str2sun(args[1]);
931 if (!sk) {
932 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
933 args[1], (int)sizeof(sk->sun_path) - 1);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100938 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100939 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100940 struct sockaddr_in *sk = str2sa(args[1]);
941 if (!sk) {
942 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100947 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100948 if (!logsrv.u.in.sin_port)
949 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951
952 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100953 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 global.logfac1 = facility;
955 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200956 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 global.logfac2 = facility;
961 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200962 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 else {
965 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200968 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100969 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
970 char *name;
971 int len;
972
973 if (global.log_send_hostname != NULL) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT;
976 goto out;
977 }
978
979 if (*(args[1]))
980 name = args[1];
981 else
982 name = hostname;
983
984 len = strlen(name);
985
986 /* We'll add a space after the name to respect the log format */
987 free(global.log_send_hostname);
988 global.log_send_hostname = malloc(len + 2);
989 snprintf(global.log_send_hostname, len + 2, "%s ", name);
990 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200991 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
992 if (global.spread_checks != 0) {
993 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200994 err_code |= ERR_ALERT;
995 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200996 }
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001001 }
1002 global.spread_checks = atol(args[1]);
1003 if (global.spread_checks < 0 || global.spread_checks > 50) {
1004 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 }
1008 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001009 struct cfg_kw_list *kwl;
1010 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001011 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001012
1013 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1014 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1015 if (kwl->kw[index].section != CFG_GLOBAL)
1016 continue;
1017 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1018 /* prepare error message just in case */
1019 snprintf(trash, sizeof(trash),
1020 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001021 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1022 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001023 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001024 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001025 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001026 else if (rc > 0) {
1027 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001028 err_code |= ERR_WARN;
1029 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001032 }
1033 }
1034 }
1035
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001039
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 out:
1041 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042}
1043
Willy Tarreau97cb7802010-01-03 20:23:58 +01001044/* Perform the most basic initialization of a proxy :
1045 * memset(), list_init(*), reset_timeouts(*).
1046 */
1047static void init_new_proxy(struct proxy *p)
1048{
1049 memset(p, 0, sizeof(struct proxy));
1050 LIST_INIT(&p->pendconns);
1051 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001052 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001053 LIST_INIT(&p->block_cond);
1054 LIST_INIT(&p->redirect_rules);
1055 LIST_INIT(&p->mon_fail_cond);
1056 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001057 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001058 LIST_INIT(&p->sticking_rules);
1059 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001060 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001061 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001062 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001063 LIST_INIT(&p->req_add);
1064 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001065
1066 /* Timeouts are defined as -1 */
1067 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001068 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001069}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001071void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001073 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 defproxy.mode = PR_MODE_TCP;
1075 defproxy.state = PR_STNEW;
1076 defproxy.maxconn = cfg_maxpconn;
1077 defproxy.conn_retries = CONN_RETRIES;
1078 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001079
1080 defproxy.defsrv.inter = DEF_CHKINTR;
1081 defproxy.defsrv.fastinter = 0;
1082 defproxy.defsrv.downinter = 0;
1083 defproxy.defsrv.rise = DEF_RISETIME;
1084 defproxy.defsrv.fall = DEF_FALLTIME;
1085 defproxy.defsrv.check_port = 0;
1086 defproxy.defsrv.maxqueue = 0;
1087 defproxy.defsrv.minconn = 0;
1088 defproxy.defsrv.maxconn = 0;
1089 defproxy.defsrv.slowstart = 0;
1090 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1091 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1092 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093}
1094
Willy Tarreauade5ec42010-01-28 19:33:49 +01001095
1096static int create_cond_regex_rule(const char *file, int line,
1097 struct proxy *px, int dir, int action, int flags,
1098 const char *cmd, const char *reg, const char *repl,
1099 const char **cond_start)
1100{
1101 regex_t *preg = NULL;
1102 const char *err;
1103 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001104 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001105
1106 if (px == &defproxy) {
1107 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto err;
1110 }
1111
1112 if (*reg == 0) {
1113 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto err;
1116 }
1117
1118 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1119 err_code |= ERR_WARN;
1120
Willy Tarreau5321c422010-01-28 20:35:13 +01001121 if (cond_start &&
1122 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1123 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1124 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1125 file, line, cmd);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto err;
1128 }
1129 }
1130 else if (cond_start && **cond_start) {
1131 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1132 file, line, cmd, *cond_start);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (dir == ACL_DIR_REQ)
1138 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001139 else
1140 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001141
Willy Tarreauade5ec42010-01-28 19:33:49 +01001142 preg = calloc(1, sizeof(regex_t));
1143 if (!preg) {
1144 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1145 err_code = ERR_ALERT | ERR_FATAL;
1146 goto err;
1147 }
1148
1149 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1150 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1151 err_code = ERR_ALERT | ERR_FATAL;
1152 goto err;
1153 }
1154
1155 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001156 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001157 if (repl && err) {
1158 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1159 file, line, cmd, *err);
1160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
1164 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1165 err_code |= ERR_WARN;
1166
1167 return err_code;
1168 err:
1169 free(preg);
1170 return err_code;
1171}
1172
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001174 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001175 * Returns the error code, 0 if OK, or any combination of :
1176 * - ERR_ABORT: must abort ASAP
1177 * - ERR_FATAL: we can continue parsing but not start the service
1178 * - ERR_WARN: a warning has been emitted
1179 * - ERR_ALERT: an alert has been emitted
1180 * Only the two first ones can stop processing, the two others are just
1181 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001183int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1184{
1185 static struct peers *curpeers = NULL;
1186 struct peer *newpeer = NULL;
1187 const char *err;
1188 int err_code = 0;
1189
1190 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1191
1192 err = invalid_char(args[1]);
1193 if (err) {
1194 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1195 file, linenum, *err, args[0], args[1]);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 }
1198
1199 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1200 /*
1201 * If there are two proxies with the same name only following
1202 * combinations are allowed:
1203 */
1204 if (strcmp(curpeers->id, args[1]) == 0) {
1205 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1206 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1207 err_code |= ERR_WARN;
1208 }
1209 }
1210
1211 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1212 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1213 err_code |= ERR_ALERT | ERR_ABORT;
1214 goto out;
1215 }
1216
1217 curpeers->next = peers;
1218 peers = curpeers;
1219 curpeers->conf.file = file;
1220 curpeers->conf.line = linenum;
1221 curpeers->last_change = now.tv_sec;
1222 curpeers->id = strdup(args[1]);
1223 }
1224 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1225 char *rport, *raddr;
1226 short realport = 0;
1227 struct sockaddr_in *sk;
1228
1229 if (!*args[2]) {
1230 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 err = invalid_char(args[1]);
1237 if (err) {
1238 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1239 file, linenum, *err, args[1]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243
1244 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1245 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1246 err_code |= ERR_ALERT | ERR_ABORT;
1247 goto out;
1248 }
1249
1250 /* the peers are linked backwards first */
1251 curpeers->count++;
1252 newpeer->next = curpeers->remote;
1253 curpeers->remote = newpeer;
1254 newpeer->peers = curpeers;
1255 newpeer->conf.file = file;
1256 newpeer->conf.line = linenum;
1257
1258 newpeer->last_change = now.tv_sec;
1259 newpeer->id = strdup(args[1]);
1260
1261 raddr = strdup(args[2]);
1262 rport = strchr(raddr, ':');
1263 if (rport) {
1264 *rport++ = 0;
1265 realport = atol(rport);
1266 }
1267 if (!realport) {
1268 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272
1273 sk = str2sa(raddr);
1274 free(raddr);
1275 if (!sk) {
1276 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
1279 }
1280 newpeer->addr = *sk;
1281 newpeer->addr.sin_port = htons(realport);
1282
1283 if (strcmp(newpeer->id, localpeer) == 0) {
1284 /* Current is local peer, it define a frontend */
1285 newpeer->local = 1;
1286
1287 if (!curpeers->peers_fe) {
1288 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1290 err_code |= ERR_ALERT | ERR_ABORT;
1291 goto out;
1292 }
1293 curpeers->peers_fe->parent = curpeers;
1294
1295 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1296 LIST_INIT(&(curpeers->peers_fe)->acl);
1297 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1298 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1299 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1300 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1301 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1302 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1303
1304 proxy_reset_timeouts(curpeers->peers_fe);
1305
1306 curpeers->peers_fe->last_change = now.tv_sec;
1307 curpeers->peers_fe->id = strdup(args[1]);
1308 curpeers->peers_fe->cap = PR_CAP_FE;
1309 curpeers->peers_fe->maxconn = 65000;
1310 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1311 curpeers->peers_fe->timeout.connect = 5000;
1312 curpeers->peers_fe->accept = peer_accept;
1313 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1314 if (!str2listener(args[2], curpeers->peers_fe)) {
1315 err_code |= ERR_FATAL;
1316 goto out;
1317 }
1318 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1319 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1320 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1321 curpeers->peers_fe->listen->accept = session_accept;
1322 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1323 curpeers->peers_fe->listen->handler = process_session;
1324 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1325 }
1326 }
1327 } /* neither "peer" nor "peers" */
1328 else if (*args[0] != 0) {
1329 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
1334out:
1335 return err_code;
1336}
1337
1338
Willy Tarreau3842f002009-06-14 11:39:52 +02001339int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340{
1341 static struct proxy *curproxy = NULL;
1342 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001343 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001344 int rc;
1345 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001346 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001347 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348
Willy Tarreau977b8e42006-12-29 14:19:17 +01001349 if (!strcmp(args[0], "listen"))
1350 rc = PR_CAP_LISTEN;
1351 else if (!strcmp(args[0], "frontend"))
1352 rc = PR_CAP_FE | PR_CAP_RS;
1353 else if (!strcmp(args[0], "backend"))
1354 rc = PR_CAP_BE | PR_CAP_RS;
1355 else if (!strcmp(args[0], "ruleset"))
1356 rc = PR_CAP_RS;
1357 else
1358 rc = PR_CAP_NONE;
1359
1360 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 if (!*args[1]) {
1362 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1363 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1364 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001365 err_code |= ERR_ALERT | ERR_ABORT;
1366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001368
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001369 err = invalid_char(args[1]);
1370 if (err) {
1371 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1372 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001373 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001374 }
1375
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001376 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1377 /*
1378 * If there are two proxies with the same name only following
1379 * combinations are allowed:
1380 *
1381 * listen backend frontend ruleset
1382 * listen - - - -
1383 * backend - - OK -
1384 * frontend - OK - -
1385 * ruleset - - - -
1386 */
1387
1388 if (!strcmp(curproxy->id, args[1]) &&
1389 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1390 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001391 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1392 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1393 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001394 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001395 }
1396 }
1397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001400 err_code |= ERR_ALERT | ERR_ABORT;
1401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001403
Willy Tarreau97cb7802010-01-03 20:23:58 +01001404 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 curproxy->next = proxy;
1406 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001407 curproxy->conf.file = file;
1408 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001409 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001411 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412
1413 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001414 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001415 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001416 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001417 err_code |= ERR_FATAL;
1418 goto out;
1419 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001420 new = curproxy->listen;
1421 while (new != last) {
1422 new->conf.file = file;
1423 new->conf.line = linenum;
1424 new = new->next;
1425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 global.maxsock++;
1427 }
1428
1429 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001430 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001431 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001432
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001434 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001435 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001436 curproxy->no_options = defproxy.no_options;
1437 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001438 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001439 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001440 curproxy->except_net = defproxy.except_net;
1441 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001442 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001443 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001445 if (defproxy.fwdfor_hdr_len) {
1446 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1447 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1448 }
1449
Willy Tarreaub86db342009-11-30 11:50:16 +01001450 if (defproxy.orgto_hdr_len) {
1451 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1452 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1453 }
1454
Willy Tarreau977b8e42006-12-29 14:19:17 +01001455 if (curproxy->cap & PR_CAP_FE) {
1456 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001457 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001458 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001459
1460 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001461 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1462 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001463
1464 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466
Willy Tarreau977b8e42006-12-29 14:19:17 +01001467 if (curproxy->cap & PR_CAP_BE) {
1468 curproxy->fullconn = defproxy.fullconn;
1469 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001471 if (defproxy.check_req) {
1472 curproxy->check_req = calloc(1, defproxy.check_len);
1473 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1474 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001475 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
Willy Tarreau977b8e42006-12-29 14:19:17 +01001477 if (defproxy.cookie_name)
1478 curproxy->cookie_name = strdup(defproxy.cookie_name);
1479 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001480 if (defproxy.cookie_domain)
1481 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001482
Willy Tarreau31936852010-10-06 16:59:56 +02001483 if (defproxy.cookie_maxidle)
1484 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1485
1486 if (defproxy.cookie_maxlife)
1487 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1488
Emeric Brun647caf12009-06-30 17:57:00 +02001489 if (defproxy.rdp_cookie_name)
1490 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1491 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1492
Willy Tarreau01732802007-11-01 22:48:15 +01001493 if (defproxy.url_param_name)
1494 curproxy->url_param_name = strdup(defproxy.url_param_name);
1495 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001496
Benoitaffb4812009-03-25 13:02:10 +01001497 if (defproxy.hh_name)
1498 curproxy->hh_name = strdup(defproxy.hh_name);
1499 curproxy->hh_len = defproxy.hh_len;
1500 curproxy->hh_match_domain = defproxy.hh_match_domain;
1501
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001502 if (defproxy.iface_name)
1503 curproxy->iface_name = strdup(defproxy.iface_name);
1504 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001507 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001508 if (defproxy.capture_name)
1509 curproxy->capture_name = strdup(defproxy.capture_name);
1510 curproxy->capture_namelen = defproxy.capture_namelen;
1511 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001515 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001516 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001517 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001518 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001519 curproxy->uri_auth = defproxy.uri_auth;
1520 curproxy->mon_net = defproxy.mon_net;
1521 curproxy->mon_mask = defproxy.mon_mask;
1522 if (defproxy.monitor_uri)
1523 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1524 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001525 if (defproxy.defbe.name)
1526 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001527 }
1528
1529 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001530 curproxy->timeout.connect = defproxy.timeout.connect;
1531 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001532 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001533 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001534 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001535 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001536 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001537 curproxy->source_addr = defproxy.source_addr;
1538 }
1539
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 curproxy->mode = defproxy.mode;
1541 curproxy->logfac1 = defproxy.logfac1;
1542 curproxy->logsrv1 = defproxy.logsrv1;
1543 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001544 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 curproxy->logfac2 = defproxy.logfac2;
1546 curproxy->logsrv2 = defproxy.logsrv2;
1547 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001548 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001550 curproxy->conf.used_listener_id = EB_ROOT;
1551 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001552
Willy Tarreau93893792009-07-23 13:19:11 +02001553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 }
1555 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1556 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001557 /* FIXME-20070101: we should do this too at the end of the
1558 * config parsing to free all default values.
1559 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001560 free(defproxy.check_req);
1561 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001562 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001563 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001564 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001565 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001566 free(defproxy.capture_name);
1567 free(defproxy.monitor_uri);
1568 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001569 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001570 free(defproxy.fwdfor_hdr_name);
1571 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001572 free(defproxy.orgto_hdr_name);
1573 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001574
Willy Tarreaua534fea2008-08-03 12:19:50 +02001575 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001576 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001577
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 /* we cannot free uri_auth because it might already be used */
1579 init_default_instance();
1580 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001581 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 }
1584 else if (curproxy == NULL) {
1585 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
1587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
1589
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590
1591 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001593 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001594 int cur_arg;
1595
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 if (curproxy == &defproxy) {
1597 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001598 err_code |= ERR_ALERT | ERR_FATAL;
1599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001601 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001602 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603
Emeric Bruned760922010-10-22 17:59:25 +02001604 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001605 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001606 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001610
1611 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001612
1613 /* NOTE: the following line might create several listeners if there
1614 * are comma-separated IPs or port ranges. So all further processing
1615 * will have to be applied to all listeners created after last_listen.
1616 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001617 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
1619 goto out;
1620 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001621
Willy Tarreau90a570f2009-10-04 20:54:54 +02001622 new_listen = curproxy->listen;
1623 while (new_listen != last_listen) {
1624 new_listen->conf.file = file;
1625 new_listen->conf.line = linenum;
1626 new_listen = new_listen->next;
1627 }
1628
Emeric Bruned760922010-10-22 17:59:25 +02001629 /* Set default global rights and owner for unix bind */
1630 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1631 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1632 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001633 cur_arg = 2;
1634 while (*(args[cur_arg])) {
1635 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1636#ifdef SO_BINDTODEVICE
1637 struct listener *l;
1638
Emeric Bruned760922010-10-22 17:59:25 +02001639 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1640 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1641 file, linenum, args[0], args[cur_arg]);
1642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
1644 }
1645
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001646 if (!*args[cur_arg + 1]) {
1647 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1648 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001649 err_code |= ERR_ALERT | ERR_FATAL;
1650 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001651 }
1652
1653 for (l = curproxy->listen; l != last_listen; l = l->next)
1654 l->interface = strdup(args[cur_arg + 1]);
1655
1656 global.last_checks |= LSTCHK_NETADM;
1657
1658 cur_arg += 2;
1659 continue;
1660#else
1661 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1662 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001665#endif
1666 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001667 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1668#ifdef TCP_MAXSEG
1669 struct listener *l;
1670 int mss;
1671
Emeric Bruned760922010-10-22 17:59:25 +02001672 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1673 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1674 file, linenum, args[0], args[cur_arg]);
1675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
1677 }
1678
Willy Tarreaube1b9182009-06-14 18:48:19 +02001679 if (!*args[cur_arg + 1]) {
1680 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1681 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001684 }
1685
Willy Tarreau48a7e722010-12-24 15:26:39 +01001686 mss = atoi(args[cur_arg + 1]);
1687 if (!mss || abs(mss) > 65535) {
1688 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001689 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001692 }
1693
1694 for (l = curproxy->listen; l != last_listen; l = l->next)
1695 l->maxseg = mss;
1696
1697 cur_arg += 2;
1698 continue;
1699#else
1700 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1701 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001702 err_code |= ERR_ALERT | ERR_FATAL;
1703 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001704#endif
1705 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001706
1707 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1708#ifdef TCP_DEFER_ACCEPT
1709 struct listener *l;
1710
1711 for (l = curproxy->listen; l != last_listen; l = l->next)
1712 l->options |= LI_O_DEF_ACCEPT;
1713
1714 cur_arg ++;
1715 continue;
1716#else
1717 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1718 file, linenum, args[0], args[cur_arg]);
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
1721#endif
1722 }
1723
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001724 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001725#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001726 struct listener *l;
1727
Emeric Bruned760922010-10-22 17:59:25 +02001728 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1729 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1730 file, linenum, args[0], args[cur_arg]);
1731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
1733 }
1734
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001735 for (l = curproxy->listen; l != last_listen; l = l->next)
1736 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001737
1738 cur_arg ++;
1739 continue;
1740#else
1741 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1742 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001745#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001746 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001747
Willy Tarreau8a956912010-10-15 14:27:08 +02001748 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1749 struct listener *l;
1750
1751 for (l = curproxy->listen; l != last_listen; l = l->next)
1752 l->options |= LI_O_ACC_PROXY;
1753
1754 cur_arg ++;
1755 continue;
1756 }
1757
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001758 if (!strcmp(args[cur_arg], "name")) {
1759 struct listener *l;
1760
1761 for (l = curproxy->listen; l != last_listen; l = l->next)
1762 l->name = strdup(args[cur_arg + 1]);
1763
1764 cur_arg += 2;
1765 continue;
1766 }
1767
1768 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001769 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001770 struct listener *l;
1771
1772 if (curproxy->listen->next != last_listen) {
1773 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1774 file, linenum, args[cur_arg]);
1775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
1777 }
1778
1779 if (!*args[cur_arg + 1]) {
1780 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1781 file, linenum, args[cur_arg]);
1782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
1784 }
1785
1786 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001787 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001788
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001789 if (curproxy->listen->luid <= 0) {
1790 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001791 file, linenum);
1792 err_code |= ERR_ALERT | ERR_FATAL;
1793 goto out;
1794 }
1795
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001796 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1797 if (node) {
1798 l = container_of(node, struct listener, conf.id);
1799 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1800 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1805
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001806 cur_arg += 2;
1807 continue;
1808 }
1809
Emeric Bruned760922010-10-22 17:59:25 +02001810 if (!strcmp(args[cur_arg], "mode")) {
1811
1812 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1813 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1814 file, linenum, args[0], args[cur_arg]);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818
1819 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1820
1821 cur_arg += 2;
1822 continue;
1823 }
1824
1825 if (!strcmp(args[cur_arg], "uid")) {
1826
1827 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1828 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1829 file, linenum, args[0], args[cur_arg]);
1830 err_code |= ERR_ALERT | ERR_FATAL;
1831 goto out;
1832 }
1833
1834 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1835 cur_arg += 2;
1836 continue;
1837 }
1838
1839 if (!strcmp(args[cur_arg], "gid")) {
1840
1841 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1842 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1843 file, linenum, args[0], args[cur_arg]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847
1848 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1849 cur_arg += 2;
1850 continue;
1851 }
1852
1853 if (!strcmp(args[cur_arg], "user")) {
1854 struct passwd *user;
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 user = getpwnam(args[cur_arg + 1]);
1863 if (!user) {
1864 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\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.uid = user->pw_uid;
1871 cur_arg += 2;
1872 continue;
1873 }
1874
1875 if (!strcmp(args[cur_arg], "group")) {
1876 struct group *group;
1877
1878 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1879 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1880 file, linenum, args[0], args[cur_arg]);
1881 err_code |= ERR_ALERT | ERR_FATAL;
1882 goto out;
1883 }
1884 group = getgrnam(args[cur_arg + 1]);
1885 if (!group) {
1886 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1887 file, linenum, args[0], args[cur_arg + 1 ]);
1888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
1890 }
1891
1892 curproxy->listen->perm.ux.gid = group->gr_gid;
1893 cur_arg += 2;
1894 continue;
1895 }
1896
Willy Tarreau8a956912010-10-15 14:27:08 +02001897 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 +01001898 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 }
1905 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1906 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1907 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001912 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001914
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 /* flush useless bits */
1916 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001919 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
Willy Tarreau1c47f852006-07-09 08:22:27 +02001923 if (!*args[1]) {
1924 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001928 }
1929
Willy Tarreaua534fea2008-08-03 12:19:50 +02001930 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001931 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001932 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001933 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001934 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1935
Willy Tarreau93893792009-07-23 13:19:11 +02001936 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1939 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1940 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1941 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1942 else {
1943 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 }
1947 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001948 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001949 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001950
1951 if (curproxy == &defproxy) {
1952 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_ALERT | ERR_FATAL;
1955 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001956 }
1957
1958 if (!*args[1]) {
1959 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1960 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001963 }
1964
1965 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001966 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001967
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001968 if (curproxy->uuid <= 0) {
1969 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001970 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001973 }
1974
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001975 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1976 if (node) {
1977 struct proxy *target = container_of(node, struct proxy, conf.id);
1978 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1979 file, linenum, proxy_type_str(curproxy), curproxy->id,
1980 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983 }
1984 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001985 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001986 else if (!strcmp(args[0], "description")) {
1987 int i, len=0;
1988 char *d;
1989
Cyril Bonté99ed3272010-01-24 23:29:44 +01001990 if (curproxy == &defproxy) {
1991 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1992 file, linenum, args[0]);
1993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
1995 }
1996
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001997 if (!*args[1]) {
1998 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1999 file, linenum, args[0]);
2000 return -1;
2001 }
2002
2003 for(i=1; *args[i]; i++)
2004 len += strlen(args[i])+1;
2005
2006 d = (char *)calloc(1, len);
2007 curproxy->desc = d;
2008
2009 d += sprintf(d, "%s", args[1]);
2010 for(i=2; *args[i]; i++)
2011 d += sprintf(d, " %s", args[i]);
2012
2013 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2015 curproxy->state = PR_STSTOPPED;
2016 }
2017 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2018 curproxy->state = PR_STNEW;
2019 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002020 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2021 int cur_arg = 1;
2022 unsigned int set = 0;
2023
2024 while (*args[cur_arg]) {
2025 int u;
2026 if (strcmp(args[cur_arg], "all") == 0) {
2027 set = 0;
2028 break;
2029 }
2030 else if (strcmp(args[cur_arg], "odd") == 0) {
2031 set |= 0x55555555;
2032 }
2033 else if (strcmp(args[cur_arg], "even") == 0) {
2034 set |= 0xAAAAAAAA;
2035 }
2036 else {
2037 u = str2uic(args[cur_arg]);
2038 if (u < 1 || u > 32) {
2039 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2040 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002043 }
2044 if (u > global.nbproc) {
2045 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002048 }
2049 set |= 1 << (u - 1);
2050 }
2051 cur_arg++;
2052 }
2053 curproxy->bind_proc = set;
2054 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002055 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002056 if (curproxy == &defproxy) {
2057 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002060 }
2061
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002062 err = invalid_char(args[1]);
2063 if (err) {
2064 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2065 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002066 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002067 }
2068
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002069 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2070 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2071 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002074 }
2075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2077 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 if (*(args[1]) == 0) {
2083 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002088
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002089 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002090 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002091 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002092 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002093 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 curproxy->cookie_name = strdup(args[1]);
2095 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002096
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 cur_arg = 2;
2098 while (*(args[cur_arg])) {
2099 if (!strcmp(args[cur_arg], "rewrite")) {
2100 curproxy->options |= PR_O_COOK_RW;
2101 }
2102 else if (!strcmp(args[cur_arg], "indirect")) {
2103 curproxy->options |= PR_O_COOK_IND;
2104 }
2105 else if (!strcmp(args[cur_arg], "insert")) {
2106 curproxy->options |= PR_O_COOK_INS;
2107 }
2108 else if (!strcmp(args[cur_arg], "nocache")) {
2109 curproxy->options |= PR_O_COOK_NOC;
2110 }
2111 else if (!strcmp(args[cur_arg], "postonly")) {
2112 curproxy->options |= PR_O_COOK_POST;
2113 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002114 else if (!strcmp(args[cur_arg], "preserve")) {
2115 curproxy->options2 |= PR_O2_COOK_PSV;
2116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 else if (!strcmp(args[cur_arg], "prefix")) {
2118 curproxy->options |= PR_O_COOK_PFX;
2119 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002120 else if (!strcmp(args[cur_arg], "domain")) {
2121 if (!*args[cur_arg + 1]) {
2122 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2123 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002124 err_code |= ERR_ALERT | ERR_FATAL;
2125 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002126 }
2127
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002128 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002129 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002130 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2131 " dots nor does not start with a dot."
2132 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002133 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002134 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002135 }
2136
2137 err = invalid_domainchar(args[cur_arg + 1]);
2138 if (err) {
2139 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2140 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002143 }
2144
Willy Tarreau68a897b2009-12-03 23:28:34 +01002145 if (!curproxy->cookie_domain) {
2146 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2147 } else {
2148 /* one domain was already specified, add another one by
2149 * building the string which will be returned along with
2150 * the cookie.
2151 */
2152 char *new_ptr;
2153 int new_len = strlen(curproxy->cookie_domain) +
2154 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2155 new_ptr = malloc(new_len);
2156 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2157 free(curproxy->cookie_domain);
2158 curproxy->cookie_domain = new_ptr;
2159 }
Willy Tarreau31936852010-10-06 16:59:56 +02002160 cur_arg++;
2161 }
2162 else if (!strcmp(args[cur_arg], "maxidle")) {
2163 unsigned int maxidle;
2164 const char *res;
2165
2166 if (!*args[cur_arg + 1]) {
2167 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2168 file, linenum, args[cur_arg]);
2169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
2171 }
2172
2173 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2174 if (res) {
2175 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2176 file, linenum, *res, args[cur_arg]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180 curproxy->cookie_maxidle = maxidle;
2181 cur_arg++;
2182 }
2183 else if (!strcmp(args[cur_arg], "maxlife")) {
2184 unsigned int maxlife;
2185 const char *res;
2186
2187 if (!*args[cur_arg + 1]) {
2188 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2189 file, linenum, args[cur_arg]);
2190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
2192 }
2193
2194 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2195 if (res) {
2196 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2197 file, linenum, *res, args[cur_arg]);
2198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
2200 }
2201 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002202 cur_arg++;
2203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002205 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 +02002206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }
2210 cur_arg++;
2211 }
2212 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2213 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2214 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }
2217
2218 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2219 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2220 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002223
2224 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2225 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2226 file, linenum);
2227 err_code |= ERR_ALERT | ERR_FATAL;
2228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002230 else if (!strcmp(args[0], "persist")) { /* persist */
2231 if (*(args[1]) == 0) {
2232 Alert("parsing [%s:%d] : missing persist method.\n",
2233 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002236 }
2237
2238 if (!strncmp(args[1], "rdp-cookie", 10)) {
2239 curproxy->options2 |= PR_O2_RDPC_PRST;
2240
Emeric Brunb982a3d2010-01-04 15:45:53 +01002241 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002242 const char *beg, *end;
2243
2244 beg = args[1] + 11;
2245 end = strchr(beg, ')');
2246
2247 if (!end || end == beg) {
2248 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2249 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002252 }
2253
2254 free(curproxy->rdp_cookie_name);
2255 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2256 curproxy->rdp_cookie_len = end-beg;
2257 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002258 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002259 free(curproxy->rdp_cookie_name);
2260 curproxy->rdp_cookie_name = strdup("msts");
2261 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2262 }
2263 else { /* syntax */
2264 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2265 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002268 }
2269 }
2270 else {
2271 Alert("parsing [%s:%d] : unknown persist method.\n",
2272 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002275 }
2276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002278 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002280 if (curproxy == &defproxy) {
2281 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
2284 }
2285
Willy Tarreau977b8e42006-12-29 14:19:17 +01002286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002287 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002288
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002290 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 }
2295 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002296 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 curproxy->appsession_name = strdup(args[1]);
2298 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2299 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002300 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2301 if (err) {
2302 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2303 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002306 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002307 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002308
Willy Tarreau51041c72007-09-09 21:56:53 +02002309 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2310 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_ABORT;
2312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002314
2315 cur_arg = 6;
2316 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002317 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2318 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002319 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002320 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002321 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002322 } else if (!strcmp(args[cur_arg], "prefix")) {
2323 curproxy->options2 |= PR_O2_AS_PFX;
2324 } else if (!strcmp(args[cur_arg], "mode")) {
2325 if (!*args[cur_arg + 1]) {
2326 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2327 file, linenum, args[0], args[cur_arg]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331
2332 cur_arg++;
2333 if (!strcmp(args[cur_arg], "query-string")) {
2334 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2335 curproxy->options2 |= PR_O2_AS_M_QS;
2336 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2337 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2338 curproxy->options2 |= PR_O2_AS_M_PP;
2339 } else {
2340 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
2343 }
2344 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002345 cur_arg++;
2346 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 } /* Url App Session */
2348 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002349 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002351
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002353 if (curproxy == &defproxy) {
2354 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
2358
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 if (*(args[4]) == 0) {
2360 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2361 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002365 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 curproxy->capture_name = strdup(args[2]);
2367 curproxy->capture_namelen = strlen(curproxy->capture_name);
2368 curproxy->capture_len = atol(args[4]);
2369 if (curproxy->capture_len >= CAPTURE_LEN) {
2370 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2371 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 curproxy->capture_len = CAPTURE_LEN - 1;
2374 }
2375 curproxy->to_log |= LW_COOKIE;
2376 }
2377 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2378 struct cap_hdr *hdr;
2379
2380 if (curproxy == &defproxy) {
2381 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 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385
2386 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2387 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2388 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 }
2392
2393 hdr = calloc(sizeof(struct cap_hdr), 1);
2394 hdr->next = curproxy->req_cap;
2395 hdr->name = strdup(args[3]);
2396 hdr->namelen = strlen(args[3]);
2397 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002398 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 hdr->index = curproxy->nb_req_cap++;
2400 curproxy->req_cap = hdr;
2401 curproxy->to_log |= LW_REQHDR;
2402 }
2403 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2404 struct cap_hdr *hdr;
2405
2406 if (curproxy == &defproxy) {
2407 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 +02002408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }
2411
2412 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2413 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2414 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 }
2418 hdr = calloc(sizeof(struct cap_hdr), 1);
2419 hdr->next = curproxy->rsp_cap;
2420 hdr->name = strdup(args[3]);
2421 hdr->namelen = strlen(args[3]);
2422 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002423 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 hdr->index = curproxy->nb_rsp_cap++;
2425 curproxy->rsp_cap = hdr;
2426 curproxy->to_log |= LW_RSPHDR;
2427 }
2428 else {
2429 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2430 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 }
2434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002436 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002438
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 if (*(args[1]) == 0) {
2440 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2441 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 }
2445 curproxy->conn_retries = atol(args[1]);
2446 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002447 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2448 struct req_acl_rule *req_acl;
2449
2450 if (curproxy == &defproxy) {
2451 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456
2457 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2458 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2459 file, linenum, args[0]);
2460 err_code |= ERR_WARN;
2461 }
2462
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002463 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002464
2465 if (!req_acl) {
2466 err_code |= ERR_ALERT | ERR_ABORT;
2467 goto out;
2468 }
2469
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002470 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002471 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2472 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002473 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002474 if (curproxy == &defproxy) {
2475 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002478 }
2479
Willy Tarreauef6494c2010-01-28 17:12:36 +01002480 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002481 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002485 }
2486
Willy Tarreauef6494c2010-01-28 17:12:36 +01002487 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002488 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2489 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002492 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002493
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002494 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002495 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002496 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002497 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002498 struct redirect_rule *rule;
2499 int cur_arg;
2500 int type = REDIRECT_TYPE_NONE;
2501 int code = 302;
2502 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002503 char *cookie = NULL;
2504 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002505 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002506
Cyril Bonté99ed3272010-01-24 23:29:44 +01002507 if (curproxy == &defproxy) {
2508 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002513 cur_arg = 1;
2514 while (*(args[cur_arg])) {
2515 if (!strcmp(args[cur_arg], "location")) {
2516 if (!*args[cur_arg + 1]) {
2517 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2518 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002521 }
2522
2523 type = REDIRECT_TYPE_LOCATION;
2524 cur_arg++;
2525 destination = args[cur_arg];
2526 }
2527 else if (!strcmp(args[cur_arg], "prefix")) {
2528 if (!*args[cur_arg + 1]) {
2529 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2530 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002533 }
2534
2535 type = REDIRECT_TYPE_PREFIX;
2536 cur_arg++;
2537 destination = args[cur_arg];
2538 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002539 else if (!strcmp(args[cur_arg], "set-cookie")) {
2540 if (!*args[cur_arg + 1]) {
2541 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2542 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002545 }
2546
2547 cur_arg++;
2548 cookie = args[cur_arg];
2549 cookie_set = 1;
2550 }
2551 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2552 if (!*args[cur_arg + 1]) {
2553 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2554 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002557 }
2558
2559 cur_arg++;
2560 cookie = args[cur_arg];
2561 cookie_set = 0;
2562 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 else if (!strcmp(args[cur_arg],"code")) {
2564 if (!*args[cur_arg + 1]) {
2565 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2566 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002569 }
2570 cur_arg++;
2571 code = atol(args[cur_arg]);
2572 if (code < 301 || code > 303) {
2573 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2574 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002577 }
2578 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002579 else if (!strcmp(args[cur_arg],"drop-query")) {
2580 flags |= REDIRECT_FLAG_DROP_QS;
2581 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002582 else if (!strcmp(args[cur_arg],"append-slash")) {
2583 flags |= REDIRECT_FLAG_APPEND_SLASH;
2584 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002585 else if (strcmp(args[cur_arg], "if") == 0 ||
2586 strcmp(args[cur_arg], "unless") == 0) {
2587 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2588 if (!cond) {
2589 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2590 file, linenum, args[0]);
2591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
2593 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002594 break;
2595 }
2596 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002597 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 +02002598 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601 }
2602 cur_arg++;
2603 }
2604
2605 if (type == REDIRECT_TYPE_NONE) {
2606 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2607 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002610 }
2611
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002612 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2613 rule->cond = cond;
2614 rule->rdr_str = strdup(destination);
2615 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002616 if (cookie) {
2617 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002618 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002619 */
2620 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002621 if (cookie_set) {
2622 rule->cookie_str = malloc(rule->cookie_len + 10);
2623 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2624 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2625 rule->cookie_len += 9;
2626 } else {
2627 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002628 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002629 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2630 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002631 }
2632 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002633 rule->type = type;
2634 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002635 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002636 LIST_INIT(&rule->list);
2637 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002638 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002639 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002640 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002641 struct switching_rule *rule;
2642
Willy Tarreaub099aca2008-10-12 17:26:37 +02002643 if (curproxy == &defproxy) {
2644 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002647 }
2648
Willy Tarreau55ea7572007-06-17 19:56:27 +02002649 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002651
2652 if (*(args[1]) == 0) {
2653 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002656 }
2657
Willy Tarreauef6494c2010-01-28 17:12:36 +01002658 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002659 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2660 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002663 }
2664
Willy Tarreauef6494c2010-01-28 17:12:36 +01002665 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002666 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002667 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002670 }
2671
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002672 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002673
Willy Tarreau55ea7572007-06-17 19:56:27 +02002674 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2675 rule->cond = cond;
2676 rule->be.name = strdup(args[1]);
2677 LIST_INIT(&rule->list);
2678 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2679 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002680 else if ((!strcmp(args[0], "force-persist")) ||
2681 (!strcmp(args[0], "ignore-persist"))) {
2682 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002683
2684 if (curproxy == &defproxy) {
2685 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
2689
2690 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2691 err_code |= ERR_WARN;
2692
Willy Tarreauef6494c2010-01-28 17:12:36 +01002693 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002694 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2695 file, linenum, args[0]);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699
Willy Tarreauef6494c2010-01-28 17:12:36 +01002700 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002701 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2702 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
2706
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002707 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002708
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002709 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002710 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002711 if (!strcmp(args[0], "force-persist")) {
2712 rule->type = PERSIST_TYPE_FORCE;
2713 } else {
2714 rule->type = PERSIST_TYPE_IGNORE;
2715 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002716 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002717 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002718 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002719 else if (!strcmp(args[0], "stick-table")) {
2720 int myidx = 1;
2721
Emeric Brun32da3c42010-09-23 18:39:19 +02002722 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002723 curproxy->table.type = (unsigned int)-1;
2724 while (*args[myidx]) {
2725 const char *err;
2726
2727 if (strcmp(args[myidx], "size") == 0) {
2728 myidx++;
2729 if (!*(args[myidx])) {
2730 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2731 file, linenum, args[myidx-1]);
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2736 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2737 file, linenum, *err, args[myidx-1]);
2738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
2740 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002741 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002742 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002743 else if (strcmp(args[myidx], "peers") == 0) {
2744 myidx++;
2745 if (!*(args[myidx])) {
2746 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2747 file, linenum, args[myidx-1]);
2748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
2751 curproxy->table.peers.name = strdup(args[myidx++]);
2752 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002753 else if (strcmp(args[myidx], "expire") == 0) {
2754 myidx++;
2755 if (!*(args[myidx])) {
2756 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2757 file, linenum, args[myidx-1]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2762 if (err) {
2763 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2764 file, linenum, *err, args[myidx-1]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002769 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002770 }
2771 else if (strcmp(args[myidx], "nopurge") == 0) {
2772 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002773 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002774 }
2775 else if (strcmp(args[myidx], "type") == 0) {
2776 myidx++;
2777 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2778 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2779 file, linenum, args[myidx]);
2780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002783 /* myidx already points to next arg */
2784 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002785 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002786 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002787 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002788
2789 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002790 nw = args[myidx];
2791 while (*nw) {
2792 /* the "store" keyword supports a comma-separated list */
2793 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002794 sa = NULL; /* store arg */
2795 while (*nw && *nw != ',') {
2796 if (*nw == '(') {
2797 *nw = 0;
2798 sa = ++nw;
2799 while (*nw != ')') {
2800 if (!*nw) {
2801 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2802 file, linenum, args[0], cw);
2803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
2805 }
2806 nw++;
2807 }
2808 *nw = '\0';
2809 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002810 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002811 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002812 if (*nw)
2813 *nw++ = '\0';
2814 type = stktable_get_data_type(cw);
2815 if (type < 0) {
2816 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2817 file, linenum, args[0], cw);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
2820 }
Willy Tarreauac782882010-06-20 10:41:54 +02002821
2822 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2823 switch (err) {
2824 case PE_NONE: break;
2825 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002826 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2827 file, linenum, args[0], cw);
2828 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002829 break;
2830
2831 case PE_ARG_MISSING:
2832 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2833 file, linenum, args[0], cw);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836
2837 case PE_ARG_NOT_USED:
2838 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2839 file, linenum, args[0], cw);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842
2843 default:
2844 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2845 file, linenum, args[0], cw);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002848 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002849 }
2850 myidx++;
2851 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002852 else {
2853 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2854 file, linenum, args[myidx]);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002857 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002858 }
2859
2860 if (!curproxy->table.size) {
2861 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2862 file, linenum);
2863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
2865 }
2866
2867 if (curproxy->table.type == (unsigned int)-1) {
2868 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2869 file, linenum);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873 }
2874 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002875 struct sticking_rule *rule;
2876 struct pattern_expr *expr;
2877 int myidx = 0;
2878 const char *name = NULL;
2879 int flags;
2880
2881 if (curproxy == &defproxy) {
2882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
2887 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2888 err_code |= ERR_WARN;
2889 goto out;
2890 }
2891
2892 myidx++;
2893 if ((strcmp(args[myidx], "store") == 0) ||
2894 (strcmp(args[myidx], "store-request") == 0)) {
2895 myidx++;
2896 flags = STK_IS_STORE;
2897 }
2898 else if (strcmp(args[myidx], "store-response") == 0) {
2899 myidx++;
2900 flags = STK_IS_STORE | STK_ON_RSP;
2901 }
2902 else if (strcmp(args[myidx], "match") == 0) {
2903 myidx++;
2904 flags = STK_IS_MATCH;
2905 }
2906 else if (strcmp(args[myidx], "on") == 0) {
2907 myidx++;
2908 flags = STK_IS_MATCH | STK_IS_STORE;
2909 }
2910 else {
2911 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
2916 if (*(args[myidx]) == 0) {
2917 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920 }
2921
Emeric Brun485479d2010-09-23 18:02:19 +02002922 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002923 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002924 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
2927 }
2928
2929 if (flags & STK_ON_RSP) {
2930 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2931 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2932 file, linenum, args[0], expr->fetch->kw);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936 } else {
2937 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2938 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2939 file, linenum, args[0], expr->fetch->kw);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943 }
2944
2945 if (strcmp(args[myidx], "table") == 0) {
2946 myidx++;
2947 name = args[myidx++];
2948 }
2949
Willy Tarreauef6494c2010-01-28 17:12:36 +01002950 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2951 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002952 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2953 file, linenum, args[0]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002957 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002958 else if (*(args[myidx])) {
2959 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2960 file, linenum, args[0], args[myidx]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
Emeric Brun97679e72010-09-23 17:56:44 +02002964 if (flags & STK_ON_RSP)
2965 err_code |= warnif_cond_requires_req(cond, file, linenum);
2966 else
2967 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002968
Emeric Brunb982a3d2010-01-04 15:45:53 +01002969 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2970 rule->cond = cond;
2971 rule->expr = expr;
2972 rule->flags = flags;
2973 rule->table.name = name ? strdup(name) : NULL;
2974 LIST_INIT(&rule->list);
2975 if (flags & STK_ON_RSP)
2976 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2977 else
2978 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002981 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002983
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2985 curproxy->uri_auth = NULL; /* we must detach from the default config */
2986
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002987 if (!*args[1]) {
2988 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002989 } else if (!strcmp(args[1], "admin")) {
2990 struct stats_admin_rule *rule;
2991
2992 if (curproxy == &defproxy) {
2993 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997
2998 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2999 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3000 err_code |= ERR_ALERT | ERR_ABORT;
3001 goto out;
3002 }
3003
3004 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3005 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3006 file, linenum, args[0], args[1]);
3007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
3009 }
3010 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3011 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3012 file, linenum, args[0], args[1]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016
3017 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3018
3019 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3020 rule->cond = cond;
3021 LIST_INIT(&rule->list);
3022 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 } else if (!strcmp(args[1], "uri")) {
3024 if (*(args[2]) == 0) {
3025 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3029 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_ABORT;
3031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
3033 } else if (!strcmp(args[1], "realm")) {
3034 if (*(args[2]) == 0) {
3035 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3039 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_ABORT;
3041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003043 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003044 unsigned interval;
3045
3046 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3047 if (err) {
3048 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3049 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003052 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3053 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_ABORT;
3055 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003056 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003057 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3058 struct req_acl_rule *req_acl;
3059
3060 if (curproxy == &defproxy) {
3061 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065
3066 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3067 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3068 err_code |= ERR_ALERT | ERR_ABORT;
3069 goto out;
3070 }
3071
3072 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3073 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3074 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3075 file, linenum, args[0]);
3076 err_code |= ERR_WARN;
3077 }
3078
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003079 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003080
3081 if (!req_acl) {
3082 err_code |= ERR_ALERT | ERR_ABORT;
3083 goto out;
3084 }
3085
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003086 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003087 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3088
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 } else if (!strcmp(args[1], "auth")) {
3090 if (*(args[2]) == 0) {
3091 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 }
3099 } else if (!strcmp(args[1], "scope")) {
3100 if (*(args[2]) == 0) {
3101 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3105 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_ABORT;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 }
3109 } else if (!strcmp(args[1], "enable")) {
3110 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3111 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_ABORT;
3113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003115 } else if (!strcmp(args[1], "hide-version")) {
3116 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3117 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_ALERT | ERR_ABORT;
3119 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003120 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003121 } else if (!strcmp(args[1], "show-legends")) {
3122 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3123 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3124 err_code |= ERR_ALERT | ERR_ABORT;
3125 goto out;
3126 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003127 } else if (!strcmp(args[1], "show-node")) {
3128
3129 if (*args[2]) {
3130 int i;
3131 char c;
3132
3133 for (i=0; args[2][i]; i++) {
3134 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003135 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3136 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003137 break;
3138 }
3139
3140 if (!i || args[2][i]) {
3141 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3142 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3143 file, linenum, args[0], args[1]);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147 }
3148
3149 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3150 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3151 err_code |= ERR_ALERT | ERR_ABORT;
3152 goto out;
3153 }
3154 } else if (!strcmp(args[1], "show-desc")) {
3155 char *desc = NULL;
3156
3157 if (*args[2]) {
3158 int i, len=0;
3159 char *d;
3160
3161 for(i=2; *args[i]; i++)
3162 len += strlen(args[i])+1;
3163
3164 desc = d = (char *)calloc(1, len);
3165
3166 d += sprintf(d, "%s", args[2]);
3167 for(i=3; *args[i]; i++)
3168 d += sprintf(d, " %s", args[i]);
3169 }
3170
3171 if (!*args[2] && !global.desc)
3172 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3173 file, linenum, args[1]);
3174 else {
3175 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3176 free(desc);
3177 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3178 err_code |= ERR_ALERT | ERR_ABORT;
3179 goto out;
3180 }
3181 free(desc);
3182 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003184stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003185 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 +01003186 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 }
3190 }
3191 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003192 int optnum;
3193
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003194 if (*(args[1]) == '\0') {
3195 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003200
3201 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3202 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003203 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3204 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3205 file, linenum, cfg_opts[optnum].name);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
Willy Tarreau93893792009-07-23 13:19:11 +02003209 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3210 err_code |= ERR_WARN;
3211 goto out;
3212 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003213
Willy Tarreau3842f002009-06-14 11:39:52 +02003214 curproxy->no_options &= ~cfg_opts[optnum].val;
3215 curproxy->options &= ~cfg_opts[optnum].val;
3216
3217 switch (kwm) {
3218 case KWM_STD:
3219 curproxy->options |= cfg_opts[optnum].val;
3220 break;
3221 case KWM_NO:
3222 curproxy->no_options |= cfg_opts[optnum].val;
3223 break;
3224 case KWM_DEF: /* already cleared */
3225 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003226 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003227
Willy Tarreau93893792009-07-23 13:19:11 +02003228 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003229 }
3230 }
3231
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003232 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3233 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003234 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3235 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3236 file, linenum, cfg_opts2[optnum].name);
3237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
3239 }
Willy Tarreau93893792009-07-23 13:19:11 +02003240 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3241 err_code |= ERR_WARN;
3242 goto out;
3243 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003244
Willy Tarreau3842f002009-06-14 11:39:52 +02003245 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3246 curproxy->options2 &= ~cfg_opts2[optnum].val;
3247
3248 switch (kwm) {
3249 case KWM_STD:
3250 curproxy->options2 |= cfg_opts2[optnum].val;
3251 break;
3252 case KWM_NO:
3253 curproxy->no_options2 |= cfg_opts2[optnum].val;
3254 break;
3255 case KWM_DEF: /* already cleared */
3256 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003257 }
Willy Tarreau93893792009-07-23 13:19:11 +02003258 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003259 }
3260 }
3261
Willy Tarreau3842f002009-06-14 11:39:52 +02003262 if (kwm != KWM_STD) {
3263 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003264 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003267 }
3268
Emeric Brun3a058f32009-06-30 18:26:00 +02003269 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003271 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003273 if (*(args[2]) != '\0') {
3274 if (!strcmp(args[2], "clf")) {
3275 curproxy->options2 |= PR_O2_CLFLOG;
3276 } else {
3277 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003280 }
3281 }
3282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 else if (!strcmp(args[1], "tcplog"))
3284 /* generate a detailed TCP log */
3285 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 else if (!strcmp(args[1], "tcpka")) {
3287 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003288 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003290
3291 if (curproxy->cap & PR_CAP_FE)
3292 curproxy->options |= PR_O_TCP_CLI_KA;
3293 if (curproxy->cap & PR_CAP_BE)
3294 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
3296 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003297 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_WARN;
3299
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003301 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003302 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003303 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003304 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003305 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003306 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003307 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 if (!*args[2]) { /* no argument */
3309 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3310 curproxy->check_len = strlen(DEF_CHECK_REQ);
3311 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003312 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 curproxy->check_req = (char *)malloc(reqlen);
3314 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003315 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003317 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 if (*args[4])
3319 reqlen += strlen(args[4]);
3320 else
3321 reqlen += strlen("HTTP/1.0");
3322
3323 curproxy->check_req = (char *)malloc(reqlen);
3324 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003325 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003327 }
3328 else if (!strcmp(args[1], "ssl-hello-chk")) {
3329 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003332
Willy Tarreaua534fea2008-08-03 12:19:50 +02003333 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003334 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003335 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003336 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003337 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003338 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003339 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
Willy Tarreau23677902007-05-08 23:50:35 +02003341 else if (!strcmp(args[1], "smtpchk")) {
3342 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003343 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003344 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003345 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003346 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003347 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003348 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003349 curproxy->options |= PR_O_SMTP_CHK;
3350
3351 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3352 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3353 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3354 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3355 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3356 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3357 curproxy->check_req = (char *)malloc(reqlen);
3358 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3359 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3360 } else {
3361 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3362 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3363 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3364 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3365 }
3366 }
3367 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003368 else if (!strcmp(args[1], "mysql-check")) {
3369 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003370 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3371 err_code |= ERR_WARN;
3372
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003373 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003374 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003375 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003376 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003377 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003378 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003379 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003380
3381 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3382 * const char mysql40_client_auth_pkt[] = {
3383 * "\x0e\x00\x00" // packet length
3384 * "\x01" // packet number
3385 * "\x00\x00" // client capabilities
3386 * "\x00\x00\x01" // max packet
3387 * "haproxy\x00" // username (null terminated string)
3388 * "\x00" // filler (always 0x00)
3389 * "\x01\x00\x00" // packet length
3390 * "\x00" // packet number
3391 * "\x01" // COM_QUIT command
3392 * };
3393 */
3394
3395 if (*(args[2])) {
3396 int cur_arg = 2;
3397
3398 while (*(args[cur_arg])) {
3399 if (strcmp(args[cur_arg], "user") == 0) {
3400 char *mysqluser;
3401 int packetlen, reqlen, userlen;
3402
3403 /* suboption header - needs additional argument for it */
3404 if (*(args[cur_arg+1]) == 0) {
3405 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3406 file, linenum, args[0], args[1], args[cur_arg]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
3410 mysqluser = args[cur_arg + 1];
3411 userlen = strlen(mysqluser);
3412 packetlen = userlen + 7;
3413 reqlen = packetlen + 9;
3414
3415 free(curproxy->check_req);
3416 curproxy->check_req = (char *)calloc(1, reqlen);
3417 curproxy->check_len = reqlen;
3418
3419 snprintf(curproxy->check_req, 4, "%c%c%c",
3420 ((unsigned char) packetlen & 0xff),
3421 ((unsigned char) (packetlen >> 8) & 0xff),
3422 ((unsigned char) (packetlen >> 16) & 0xff));
3423
3424 curproxy->check_req[3] = 1;
3425 curproxy->check_req[8] = 1;
3426 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3427 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3428 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3429 cur_arg += 2;
3430 } else {
3431 /* unknown suboption - catchall */
3432 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3433 file, linenum, args[0], args[1]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437 } /* end while loop */
3438 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003439 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003440 else if (!strcmp(args[1], "ldap-check")) {
3441 /* use LDAP request to check servers' health */
3442 free(curproxy->check_req);
3443 curproxy->check_req = NULL;
3444 curproxy->options &= ~PR_O_HTTP_CHK;
3445 curproxy->options &= ~PR_O_SMTP_CHK;
3446 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3447 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3448 curproxy->options2 |= PR_O2_LDAP_CHK;
3449
3450 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3451 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3452 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3453 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003454 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003455 int cur_arg;
3456
3457 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3458 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003459 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003460
3461 curproxy->options |= PR_O_FWDFOR;
3462
3463 free(curproxy->fwdfor_hdr_name);
3464 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3465 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3466
3467 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3468 cur_arg = 2;
3469 while (*(args[cur_arg])) {
3470 if (!strcmp(args[cur_arg], "except")) {
3471 /* suboption except - needs additional argument for it */
3472 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3473 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3474 file, linenum, args[0], args[1], args[cur_arg]);
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 }
3478 /* flush useless bits */
3479 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003480 cur_arg += 2;
3481 } else if (!strcmp(args[cur_arg], "header")) {
3482 /* suboption header - needs additional argument for it */
3483 if (*(args[cur_arg+1]) == 0) {
3484 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3485 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003486 err_code |= ERR_ALERT | ERR_FATAL;
3487 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003488 }
3489 free(curproxy->fwdfor_hdr_name);
3490 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3491 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3492 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003493 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003494 /* unknown suboption - catchall */
3495 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3496 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003499 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003500 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003501 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003502 else if (!strcmp(args[1], "originalto")) {
3503 int cur_arg;
3504
3505 /* insert x-original-to field, but not for the IP address listed as an except.
3506 * set default options (ie: bitfield, header name, etc)
3507 */
3508
3509 curproxy->options |= PR_O_ORGTO;
3510
3511 free(curproxy->orgto_hdr_name);
3512 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3513 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3514
3515 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3516 cur_arg = 2;
3517 while (*(args[cur_arg])) {
3518 if (!strcmp(args[cur_arg], "except")) {
3519 /* suboption except - needs additional argument for it */
3520 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3521 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3522 file, linenum, args[0], args[1], args[cur_arg]);
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 /* flush useless bits */
3527 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3528 cur_arg += 2;
3529 } else if (!strcmp(args[cur_arg], "header")) {
3530 /* suboption header - needs additional argument for it */
3531 if (*(args[cur_arg+1]) == 0) {
3532 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3533 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003536 }
3537 free(curproxy->orgto_hdr_name);
3538 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3539 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3540 cur_arg += 2;
3541 } else {
3542 /* unknown suboption - catchall */
3543 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3544 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003547 }
3548 } /* end while loop */
3549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 else {
3551 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
Willy Tarreau93893792009-07-23 13:19:11 +02003555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003556 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003557 else if (!strcmp(args[0], "default_backend")) {
3558 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003560
3561 if (*(args[1]) == 0) {
3562 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003565 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003566 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003567 curproxy->defbe.name = strdup(args[1]);
3568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003570 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003572
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003573 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 /* enable reconnections to dispatch */
3577 curproxy->options |= PR_O_REDISP;
3578 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003579 else if (!strcmp(args[0], "http-check")) {
3580 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003582
3583 if (strcmp(args[1], "disable-on-404") == 0) {
3584 /* enable a graceful server shutdown on an HTTP 404 response */
3585 curproxy->options |= PR_O_DISABLE404;
3586 }
Willy Tarreauef781042010-01-27 11:53:01 +01003587 else if (strcmp(args[1], "send-state") == 0) {
3588 /* enable emission of the apparent state of a server in HTTP checks */
3589 curproxy->options2 |= PR_O2_CHK_SNDST;
3590 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003591 else if (strcmp(args[1], "expect") == 0) {
3592 const char *ptr_arg;
3593 int cur_arg;
3594
3595 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3596 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
3599 }
3600
3601 cur_arg = 2;
3602 /* consider exclamation marks, sole or at the beginning of a word */
3603 while (*(ptr_arg = args[cur_arg])) {
3604 while (*ptr_arg == '!') {
3605 curproxy->options2 ^= PR_O2_EXP_INV;
3606 ptr_arg++;
3607 }
3608 if (*ptr_arg)
3609 break;
3610 cur_arg++;
3611 }
3612 /* now ptr_arg points to the beginning of a word past any possible
3613 * exclamation mark, and cur_arg is the argument which holds this word.
3614 */
3615 if (strcmp(ptr_arg, "status") == 0) {
3616 if (!*(args[cur_arg + 1])) {
3617 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3618 file, linenum, args[0], args[1], ptr_arg);
3619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
3621 }
3622 curproxy->options2 |= PR_O2_EXP_STS;
3623 curproxy->expect_str = strdup(args[cur_arg + 1]);
3624 }
3625 else if (strcmp(ptr_arg, "string") == 0) {
3626 if (!*(args[cur_arg + 1])) {
3627 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3628 file, linenum, args[0], args[1], ptr_arg);
3629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
3631 }
3632 curproxy->options2 |= PR_O2_EXP_STR;
3633 curproxy->expect_str = strdup(args[cur_arg + 1]);
3634 }
3635 else if (strcmp(ptr_arg, "rstatus") == 0) {
3636 if (!*(args[cur_arg + 1])) {
3637 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3638 file, linenum, args[0], args[1], ptr_arg);
3639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
3641 }
3642 curproxy->options2 |= PR_O2_EXP_RSTS;
3643 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3644 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3645 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3646 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650 }
3651 else if (strcmp(ptr_arg, "rstring") == 0) {
3652 if (!*(args[cur_arg + 1])) {
3653 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3654 file, linenum, args[0], args[1], ptr_arg);
3655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
3657 }
3658 curproxy->options2 |= PR_O2_EXP_RSTR;
3659 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3660 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3661 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3662 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666 }
3667 else {
3668 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3669 file, linenum, args[0], args[1], ptr_arg);
3670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
3672 }
3673 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003674 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003675 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003678 }
3679 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003680 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003681 if (curproxy == &defproxy) {
3682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003685 }
3686
Willy Tarreaub80c2302007-11-30 20:51:32 +01003687 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003688 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003689
3690 if (strcmp(args[1], "fail") == 0) {
3691 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003692 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003693 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3694 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003697 }
3698
Willy Tarreauef6494c2010-01-28 17:12:36 +01003699 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003700 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3701 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003704 }
3705 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3706 }
3707 else {
3708 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003711 }
3712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003713#ifdef TPROXY
3714 else if (!strcmp(args[0], "transparent")) {
3715 /* enable transparent proxy connections */
3716 curproxy->options |= PR_O_TRANSP;
3717 }
3718#endif
3719 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003720 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003722
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 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 Tarreaubaaee002006-06-26 02:48:02 +02003727 }
3728 curproxy->maxconn = atol(args[1]);
3729 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003730 else if (!strcmp(args[0], "backlog")) { /* backlog */
3731 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003733
3734 if (*(args[1]) == 0) {
3735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003738 }
3739 curproxy->backlog = atol(args[1]);
3740 }
Willy Tarreau86034312006-12-29 00:10:33 +01003741 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003744
Willy Tarreau86034312006-12-29 00:10:33 +01003745 if (*(args[1]) == 0) {
3746 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003749 }
3750 curproxy->fullconn = atol(args[1]);
3751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3753 if (*(args[1]) == 0) {
3754 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003758 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3759 if (err) {
3760 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3761 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003764 }
3765 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 }
3767 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003768 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 if (curproxy == &defproxy) {
3770 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 if (strchr(args[1], ':') == NULL) {
3778 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003782 sk = str2sa(args[1]);
3783 if (!sk) {
3784 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
3787 }
3788 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
3790 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003791 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003793
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003794 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003795 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3796 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003801 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3803 err_code |= ERR_WARN;
3804
3805 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3806 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3807 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3808 }
3809 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3810 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3811 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3812 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003813 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3814 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3815 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3816 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003817 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003818 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
3821 }
3822 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003823 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003825 char *rport, *raddr;
3826 short realport = 0;
3827 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003829 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003834 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836
3837 if (!*args[2]) {
3838 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3839 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003843
3844 err = invalid_char(args[1]);
3845 if (err) {
3846 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3847 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003850 }
3851
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003852 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003853 struct sockaddr_in *sk;
3854
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003855 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3856 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3857 err_code |= ERR_ALERT | ERR_ABORT;
3858 goto out;
3859 }
3860
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003861 /* the servers are linked backwards first */
3862 newsrv->next = curproxy->srv;
3863 curproxy->srv = newsrv;
3864 newsrv->proxy = curproxy;
3865 newsrv->conf.file = file;
3866 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003868 LIST_INIT(&newsrv->pendconns);
3869 do_check = 0;
3870 newsrv->state = SRV_RUNNING; /* early server setup */
3871 newsrv->last_change = now.tv_sec;
3872 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003874 /* several ways to check the port component :
3875 * - IP => port=+0, relative
3876 * - IP: => port=+0, relative
3877 * - IP:N => port=N, absolute
3878 * - IP:+N => port=+N, relative
3879 * - IP:-N => port=-N, relative
3880 */
3881 raddr = strdup(args[2]);
3882 rport = strchr(raddr, ':');
3883 if (rport) {
3884 *rport++ = 0;
3885 realport = atol(rport);
3886 if (!isdigit((unsigned char)*rport))
3887 newsrv->state |= SRV_MAPPORTS;
3888 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003890
Willy Tarreaud5191e72010-02-09 20:50:45 +01003891 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003892 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003893 if (!sk) {
3894 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
3897 }
3898 newsrv->addr = *sk;
3899 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003900
3901 newsrv->check_port = curproxy->defsrv.check_port;
3902 newsrv->inter = curproxy->defsrv.inter;
3903 newsrv->fastinter = curproxy->defsrv.fastinter;
3904 newsrv->downinter = curproxy->defsrv.downinter;
3905 newsrv->rise = curproxy->defsrv.rise;
3906 newsrv->fall = curproxy->defsrv.fall;
3907 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3908 newsrv->minconn = curproxy->defsrv.minconn;
3909 newsrv->maxconn = curproxy->defsrv.maxconn;
3910 newsrv->slowstart = curproxy->defsrv.slowstart;
3911 newsrv->onerror = curproxy->defsrv.onerror;
3912 newsrv->consecutive_errors_limit
3913 = curproxy->defsrv.consecutive_errors_limit;
3914 newsrv->uweight = newsrv->iweight
3915 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003917 newsrv->curfd = -1; /* no health-check in progress */
3918 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003920 cur_arg = 3;
3921 } else {
3922 newsrv = &curproxy->defsrv;
3923 cur_arg = 1;
3924 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003925
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003927 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003928 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003929
3930 if (!*args[cur_arg + 1]) {
3931 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3932 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003935 }
3936
3937 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003938 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003939
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003940 if (newsrv->puid <= 0) {
3941 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003942 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003945 }
3946
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003947 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3948 if (node) {
3949 struct server *target = container_of(node, struct server, conf.id);
3950 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3951 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
3954 }
3955 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003956 cur_arg += 2;
3957 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003958 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 newsrv->cookie = strdup(args[cur_arg + 1]);
3960 newsrv->cklen = strlen(args[cur_arg + 1]);
3961 cur_arg += 2;
3962 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003963 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003964 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3965 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3966 cur_arg += 2;
3967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003969 if (!*args[cur_arg + 1]) {
3970 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3971 file, linenum, args[cur_arg]);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003977 if (newsrv->rise <= 0) {
3978 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3979 file, linenum, args[cur_arg]);
3980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
3982 }
3983
Willy Tarreau96839092010-03-29 10:02:24 +02003984 if (newsrv->health)
3985 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 cur_arg += 2;
3987 }
3988 else if (!strcmp(args[cur_arg], "fall")) {
3989 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003990
3991 if (!*args[cur_arg + 1]) {
3992 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3993 file, linenum, args[cur_arg]);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
3996 }
3997
3998 if (newsrv->fall <= 0) {
3999 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4000 file, linenum, args[cur_arg]);
4001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
4003 }
4004
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 cur_arg += 2;
4006 }
4007 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004008 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4009 if (err) {
4010 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4011 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004014 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004015 if (val <= 0) {
4016 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4017 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004020 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004021 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 cur_arg += 2;
4023 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004024 else if (!strcmp(args[cur_arg], "fastinter")) {
4025 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4026 if (err) {
4027 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4028 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004031 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004032 if (val <= 0) {
4033 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4034 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004037 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004038 newsrv->fastinter = val;
4039 cur_arg += 2;
4040 }
4041 else if (!strcmp(args[cur_arg], "downinter")) {
4042 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4043 if (err) {
4044 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4045 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004048 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004049 if (val <= 0) {
4050 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4051 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004054 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004055 newsrv->downinter = val;
4056 cur_arg += 2;
4057 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004058 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004059 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4060 if (!sk) {
4061 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004066 cur_arg += 2;
4067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 else if (!strcmp(args[cur_arg], "port")) {
4069 newsrv->check_port = atol(args[cur_arg + 1]);
4070 cur_arg += 2;
4071 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004072 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 newsrv->state |= SRV_BACKUP;
4074 cur_arg ++;
4075 }
4076 else if (!strcmp(args[cur_arg], "weight")) {
4077 int w;
4078 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004079 if (w < 0 || w > 256) {
4080 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004084 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004085 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 cur_arg += 2;
4087 }
4088 else if (!strcmp(args[cur_arg], "minconn")) {
4089 newsrv->minconn = atol(args[cur_arg + 1]);
4090 cur_arg += 2;
4091 }
4092 else if (!strcmp(args[cur_arg], "maxconn")) {
4093 newsrv->maxconn = atol(args[cur_arg + 1]);
4094 cur_arg += 2;
4095 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004096 else if (!strcmp(args[cur_arg], "maxqueue")) {
4097 newsrv->maxqueue = atol(args[cur_arg + 1]);
4098 cur_arg += 2;
4099 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004100 else if (!strcmp(args[cur_arg], "slowstart")) {
4101 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004102 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004103 if (err) {
4104 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4105 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004108 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004109 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004110 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4111 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004114 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004115 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004116 cur_arg += 2;
4117 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004118 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004119
4120 if (!*args[cur_arg + 1]) {
4121 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4122 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004125 }
4126
4127 newsrv->trackit = strdup(args[cur_arg + 1]);
4128
4129 cur_arg += 2;
4130 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004131 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 global.maxsock++;
4133 do_check = 1;
4134 cur_arg += 1;
4135 }
Willy Tarreau96839092010-03-29 10:02:24 +02004136 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4137 newsrv->state |= SRV_MAINTAIN;
4138 newsrv->state &= ~SRV_RUNNING;
4139 newsrv->health = 0;
4140 cur_arg += 1;
4141 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004142 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004143 if (!strcmp(args[cur_arg + 1], "none"))
4144 newsrv->observe = HANA_OBS_NONE;
4145 else if (!strcmp(args[cur_arg + 1], "layer4"))
4146 newsrv->observe = HANA_OBS_LAYER4;
4147 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4148 if (curproxy->mode != PR_MODE_HTTP) {
4149 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4150 file, linenum, args[cur_arg + 1]);
4151 err_code |= ERR_ALERT;
4152 }
4153 newsrv->observe = HANA_OBS_LAYER7;
4154 }
4155 else {
4156 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004157 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004158 file, linenum, args[cur_arg], args[cur_arg + 1]);
4159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
4161 }
4162
4163 cur_arg += 2;
4164 }
4165 else if (!strcmp(args[cur_arg], "on-error")) {
4166 if (!strcmp(args[cur_arg + 1], "fastinter"))
4167 newsrv->onerror = HANA_ONERR_FASTINTER;
4168 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4169 newsrv->onerror = HANA_ONERR_FAILCHK;
4170 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4171 newsrv->onerror = HANA_ONERR_SUDDTH;
4172 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4173 newsrv->onerror = HANA_ONERR_MARKDWN;
4174 else {
4175 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004176 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004177 file, linenum, args[cur_arg], args[cur_arg + 1]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181
4182 cur_arg += 2;
4183 }
4184 else if (!strcmp(args[cur_arg], "error-limit")) {
4185 if (!*args[cur_arg + 1]) {
4186 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4187 file, linenum, args[cur_arg]);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190 }
4191
4192 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4193
4194 if (newsrv->consecutive_errors_limit <= 0) {
4195 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4196 file, linenum, args[cur_arg]);
4197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
4199 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004200 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004201 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004202 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004203 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004204 struct sockaddr_in *sk;
4205
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004207#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004208 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004209 file, linenum, "source", "usesrc");
4210#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004211 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004213#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 }
4217 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004218 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4219 if (!sk) {
4220 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223 }
4224 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004225
4226 if (port_low != port_high) {
4227 int i;
4228 if (port_low <= 0 || port_low > 65535 ||
4229 port_high <= 0 || port_high > 65535 ||
4230 port_low > port_high) {
4231 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4232 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004235 }
4236 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4237 for (i = 0; i < newsrv->sport_range->size; i++)
4238 newsrv->sport_range->ports[i] = port_low + i;
4239 }
4240
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004242 while (*(args[cur_arg])) {
4243 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004244#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4245#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004246 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4247 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4248 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004251 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004252#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004253 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004254 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004255 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004258 }
4259 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004260 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004261 newsrv->state |= SRV_TPROXY_CLI;
4262 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004263 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004264 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004265 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4266 char *name, *end;
4267
4268 name = args[cur_arg+1] + 7;
4269 while (isspace(*name))
4270 name++;
4271
4272 end = name;
4273 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4274 end++;
4275
4276 newsrv->state &= ~SRV_TPROXY_MASK;
4277 newsrv->state |= SRV_TPROXY_DYN;
4278 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4279 newsrv->bind_hdr_len = end - name;
4280 memcpy(newsrv->bind_hdr_name, name, end - name);
4281 newsrv->bind_hdr_name[end-name] = '\0';
4282 newsrv->bind_hdr_occ = -1;
4283
4284 /* now look for an occurrence number */
4285 while (isspace(*end))
4286 end++;
4287 if (*end == ',') {
4288 end++;
4289 name = end;
4290 if (*end == '-')
4291 end++;
4292 while (isdigit(*end))
4293 end++;
4294 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4295 }
4296
4297 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4298 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4299 " occurrences values smaller than %d.\n",
4300 file, linenum, MAX_HDR_HISTORY);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004304 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004305 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4306 if (!sk) {
4307 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004312 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004313 }
4314 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004315#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004316 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004317#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004318 cur_arg += 2;
4319 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004320#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004321 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004322 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4326 } /* "usesrc" */
4327
4328 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4329#ifdef SO_BINDTODEVICE
4330 if (!*args[cur_arg + 1]) {
4331 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4332 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004335 }
4336 if (newsrv->iface_name)
4337 free(newsrv->iface_name);
4338
4339 newsrv->iface_name = strdup(args[cur_arg + 1]);
4340 newsrv->iface_len = strlen(newsrv->iface_name);
4341 global.last_checks |= LSTCHK_NETADM;
4342#else
4343 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4344 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004347#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004348 cur_arg += 2;
4349 continue;
4350 }
4351 /* this keyword in not an option of "source" */
4352 break;
4353 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004354 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004355 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004356 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4357 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004360 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004362 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004363 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 +01004364 file, linenum, newsrv->id);
4365 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004366 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 +01004367 file, linenum);
4368
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 }
4372 }
4373
4374 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004375 if (newsrv->trackit) {
4376 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4377 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004380 }
4381
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004382 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4383 newsrv->check_port = newsrv->check_addr.sin_port;
4384
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4386 newsrv->check_port = realport; /* by default */
4387 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004388 /* not yet valid, because no port was set on
4389 * the server either. We'll check if we have
4390 * a known port on the first listener.
4391 */
4392 struct listener *l;
4393 l = curproxy->listen;
4394 if (l) {
4395 int port;
4396 port = (l->addr.ss_family == AF_INET6)
4397 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4398 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4399 newsrv->check_port = port;
4400 }
4401 }
4402 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4404 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004408
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004409 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004410 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004411 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4412 err_code |= ERR_ALERT | ERR_ABORT;
4413 goto out;
4414 }
4415
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004416 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 newsrv->state |= SRV_CHECKED;
4418 }
4419
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004420 if (!defsrv) {
4421 if (newsrv->state & SRV_BACKUP)
4422 curproxy->srv_bck++;
4423 else
4424 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004425
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004426 newsrv->prev_state = newsrv->state;
4427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 }
4429 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004430 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 int facility;
4432
4433 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4434 curproxy->logfac1 = global.logfac1;
4435 curproxy->logsrv1 = global.logsrv1;
4436 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004437 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 curproxy->logfac2 = global.logfac2;
4439 curproxy->logsrv2 = global.logsrv2;
4440 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004441 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 }
4443 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004444 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445
4446 facility = get_log_facility(args[2]);
4447 if (facility < 0) {
4448 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4449 exit(1);
4450 }
4451
4452 level = 7; /* max syslog level = debug */
4453 if (*(args[3])) {
4454 level = get_log_level(args[3]);
4455 if (level < 0) {
4456 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4457 exit(1);
4458 }
4459 }
4460
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004461 minlvl = 0; /* limit syslog level to this level (emerg) */
4462 if (*(args[4])) {
4463 minlvl = get_log_level(args[4]);
4464 if (level < 0) {
4465 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4466 exit(1);
4467 }
4468 }
4469
Robert Tsai81ae1952007-12-05 10:47:29 +01004470 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004471 struct sockaddr_un *sk = str2sun(args[1]);
4472 if (!sk) {
4473 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4474 args[1], (int)sizeof(sk->sun_path) - 1);
4475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
4477 }
4478 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004479 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004480 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004481 struct sockaddr_in *sk = str2sa(args[1]);
4482 if (!sk) {
4483 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
4486 }
4487 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004488 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004489 if (!logsrv.u.in.sin_port) {
4490 logsrv.u.in.sin_port =
4491 htons(SYSLOG_PORT);
4492 }
4493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494
4495 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004496 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 curproxy->logfac1 = facility;
4498 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004499 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 }
4501 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004502 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 curproxy->logfac2 = facility;
4504 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004505 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
4507 else {
4508 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 }
4512 }
4513 else {
4514 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4515 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
4519 }
4520 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004521 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004522 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004523
Willy Tarreau977b8e42006-12-29 14:19:17 +01004524 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004526
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004528 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4529 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004533
4534 /* we must first clear any optional default setting */
4535 curproxy->options &= ~PR_O_TPXY_MASK;
4536 free(curproxy->iface_name);
4537 curproxy->iface_name = NULL;
4538 curproxy->iface_len = 0;
4539
Willy Tarreaud5191e72010-02-09 20:50:45 +01004540 sk = str2sa(args[1]);
4541 if (!sk) {
4542 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
4545 }
4546 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004547 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004548
4549 cur_arg = 2;
4550 while (*(args[cur_arg])) {
4551 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004552#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4553#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004554 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4555 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4556 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004559 }
4560#endif
4561 if (!*args[cur_arg + 1]) {
4562 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4563 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004566 }
4567
4568 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004569 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004570 curproxy->options |= PR_O_TPXY_CLI;
4571 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004572 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004573 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004574 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4575 char *name, *end;
4576
4577 name = args[cur_arg+1] + 7;
4578 while (isspace(*name))
4579 name++;
4580
4581 end = name;
4582 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4583 end++;
4584
4585 curproxy->options &= ~PR_O_TPXY_MASK;
4586 curproxy->options |= PR_O_TPXY_DYN;
4587 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4588 curproxy->bind_hdr_len = end - name;
4589 memcpy(curproxy->bind_hdr_name, name, end - name);
4590 curproxy->bind_hdr_name[end-name] = '\0';
4591 curproxy->bind_hdr_occ = -1;
4592
4593 /* now look for an occurrence number */
4594 while (isspace(*end))
4595 end++;
4596 if (*end == ',') {
4597 end++;
4598 name = end;
4599 if (*end == '-')
4600 end++;
4601 while (isdigit(*end))
4602 end++;
4603 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4604 }
4605
4606 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4607 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4608 " occurrences values smaller than %d.\n",
4609 file, linenum, MAX_HDR_HISTORY);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004613 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004614 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4615 if (!sk) {
4616 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
4619 }
4620 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004621 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004622 }
4623 global.last_checks |= LSTCHK_NETADM;
4624#if !defined(CONFIG_HAP_LINUX_TPROXY)
4625 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004626#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004627#else /* no TPROXY support */
4628 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004629 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004632#endif
4633 cur_arg += 2;
4634 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004635 }
4636
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004637 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4638#ifdef SO_BINDTODEVICE
4639 if (!*args[cur_arg + 1]) {
4640 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004644 }
4645 if (curproxy->iface_name)
4646 free(curproxy->iface_name);
4647
4648 curproxy->iface_name = strdup(args[cur_arg + 1]);
4649 curproxy->iface_len = strlen(curproxy->iface_name);
4650 global.last_checks |= LSTCHK_NETADM;
4651#else
4652 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4653 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004656#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004657 cur_arg += 2;
4658 continue;
4659 }
4660 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4661 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004662 err_code |= ERR_ALERT | ERR_FATAL;
4663 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004666 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4667 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4668 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004673 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004674 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4675 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004676 err_code |= ERR_ALERT | ERR_FATAL;
4677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004679
4680 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4681 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004682 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004683 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 }
4686 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004687 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4688 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004689 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004690 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 }
4693 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004694 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4695 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004696 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004697 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
4700 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004701 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4702 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004703 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004704 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004706 }
4707 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004708 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4709 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004710 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004711 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004714 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004715 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4716 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004717 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004718 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004719 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004720 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004721 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004722 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4723 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004724 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004725 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004726 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004727 }
4728 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004729 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4730 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004731 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004732 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004733 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004736 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4738 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004742
4743 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4744 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004745 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004746 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
4749 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004750 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4751 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004752 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004753 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 }
4756 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004757 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4758 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004759 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004760 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
4763 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004764 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4765 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004766 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 }
4770 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004771 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4772 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004773 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004777 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004778 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4779 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004780 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004782 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004785 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004786
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 if (curproxy == &defproxy) {
4788 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004792 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004793 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 if (*(args[1]) == 0) {
4796 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004800
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004801 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4802 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4803 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4804 file, linenum, args[0]);
4805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
4807 }
4808 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4809 }
4810 else if (*args[2]) {
4811 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4812 file, linenum, args[0], args[2]);
4813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
4816
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004817 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004818 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004819 wl->s = strdup(args[1]);
4820 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004821 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 }
4823 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004824 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4826 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004830
Willy Tarreauade5ec42010-01-28 19:33:49 +01004831 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4832 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004833 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004834 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 }
4837 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004838 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4839 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004840 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004841 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 }
4844 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004845 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4846 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004847 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004848 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 }
4851 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004852 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4854 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 }
4858
Willy Tarreauade5ec42010-01-28 19:33:49 +01004859 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4860 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004861 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004862 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
4865 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004866 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4867 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004868 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004869 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
4872 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004873 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4874 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004875 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004876 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 }
4879 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004880 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004881
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 if (curproxy == &defproxy) {
4883 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004887 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 if (*(args[1]) == 0) {
4891 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
4895
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004896 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4897 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4898 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4899 file, linenum, args[0]);
4900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902 }
4903 err_code |= warnif_cond_requires_req(cond, file, linenum);
4904 }
4905 else if (*args[2]) {
4906 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4907 file, linenum, args[0], args[2]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
4911
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004912 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004913 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004914 wl->s = strdup(args[1]);
4915 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 else if (!strcmp(args[0], "errorloc") ||
4918 !strcmp(args[0], "errorloc302") ||
4919 !strcmp(args[0], "errorloc303")) { /* error location */
4920 int errnum, errlen;
4921 char *err;
4922
Willy Tarreau977b8e42006-12-29 14:19:17 +01004923 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004925
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004927 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931
4932 errnum = atol(args[1]);
4933 if (!strcmp(args[0], "errorloc303")) {
4934 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4935 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4936 } else {
4937 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4938 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4939 }
4940
Willy Tarreau0f772532006-12-23 20:51:41 +01004941 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4942 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004943 chunk_destroy(&curproxy->errmsg[rc]);
4944 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004945 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004948
4949 if (rc >= HTTP_ERR_SIZE) {
4950 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4951 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 free(err);
4953 }
4954 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004955 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4956 int errnum, errlen, fd;
4957 char *err;
4958 struct stat stat;
4959
4960 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004962
4963 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004964 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004967 }
4968
4969 fd = open(args[2], O_RDONLY);
4970 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4971 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4972 file, linenum, args[2], args[1]);
4973 if (fd >= 0)
4974 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004977 }
4978
Willy Tarreau27a674e2009-08-17 07:23:33 +02004979 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004980 errlen = stat.st_size;
4981 } else {
4982 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004983 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004985 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004986 }
4987
4988 err = malloc(errlen); /* malloc() must succeed during parsing */
4989 errnum = read(fd, err, errlen);
4990 if (errnum != errlen) {
4991 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4992 file, linenum, args[2], args[1]);
4993 close(fd);
4994 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004997 }
4998 close(fd);
4999
5000 errnum = atol(args[1]);
5001 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5002 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005003 chunk_destroy(&curproxy->errmsg[rc]);
5004 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005005 break;
5006 }
5007 }
5008
5009 if (rc >= HTTP_ERR_SIZE) {
5010 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5011 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005012 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005013 free(err);
5014 }
5015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005017 struct cfg_kw_list *kwl;
5018 int index;
5019
5020 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5021 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5022 if (kwl->kw[index].section != CFG_LISTEN)
5023 continue;
5024 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5025 /* prepare error message just in case */
5026 snprintf(trash, sizeof(trash),
5027 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005028 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5029 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005030 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005033 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005034 else if (rc > 0) {
5035 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005036 err_code |= ERR_WARN;
5037 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005038 }
Willy Tarreau93893792009-07-23 13:19:11 +02005039 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005040 }
5041 }
5042 }
5043
Willy Tarreau6daf3432008-01-22 16:44:08 +01005044 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 }
Willy Tarreau93893792009-07-23 13:19:11 +02005048 out:
5049 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050}
5051
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005052int
5053cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5054{
5055
5056 int err_code = 0;
5057 const char *err;
5058
5059 if (!strcmp(args[0], "userlist")) { /* new userlist */
5060 struct userlist *newul;
5061
5062 if (!*args[1]) {
5063 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5064 file, linenum, args[0]);
5065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
5067 }
5068
5069 err = invalid_char(args[1]);
5070 if (err) {
5071 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5072 file, linenum, *err, args[0], args[1]);
5073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
5075 }
5076
5077 for (newul = userlist; newul; newul = newul->next)
5078 if (!strcmp(newul->name, args[1])) {
5079 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5080 file, linenum, args[1]);
5081 err_code |= ERR_WARN;
5082 goto out;
5083 }
5084
5085 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5086 if (!newul) {
5087 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5088 err_code |= ERR_ALERT | ERR_ABORT;
5089 goto out;
5090 }
5091
5092 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5093 newul->name = strdup(args[1]);
5094
5095 if (!newul->groupusers | !newul->name) {
5096 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5097 err_code |= ERR_ALERT | ERR_ABORT;
5098 goto out;
5099 }
5100
5101 newul->next = userlist;
5102 userlist = newul;
5103
5104 } else if (!strcmp(args[0], "group")) { /* new group */
5105 int cur_arg, i;
5106 const char *err;
5107
5108 if (!*args[1]) {
5109 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5110 file, linenum, args[0]);
5111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
5113 }
5114
5115 err = invalid_char(args[1]);
5116 if (err) {
5117 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5118 file, linenum, *err, args[0], args[1]);
5119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
5121 }
5122
5123 for(i = 0; i < userlist->grpcnt; i++)
5124 if (!strcmp(userlist->groups[i], args[1])) {
5125 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5126 file, linenum, args[1], userlist->name);
5127 err_code |= ERR_ALERT;
5128 goto out;
5129 }
5130
5131 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5132 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5133 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
5136 }
5137
5138 cur_arg = 2;
5139
5140 while (*args[cur_arg]) {
5141 if (!strcmp(args[cur_arg], "users")) {
5142 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5143 cur_arg += 2;
5144 continue;
5145 } else {
5146 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5147 file, linenum, args[0]);
5148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
5150 }
5151 }
5152
5153 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5154 } else if (!strcmp(args[0], "user")) { /* new user */
5155 struct auth_users *newuser;
5156 int cur_arg;
5157
5158 if (!*args[1]) {
5159 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5160 file, linenum, args[0]);
5161 err_code |= ERR_ALERT | ERR_FATAL;
5162 goto out;
5163 }
5164
5165 for (newuser = userlist->users; newuser; newuser = newuser->next)
5166 if (!strcmp(newuser->user, args[1])) {
5167 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5168 file, linenum, args[1], userlist->name);
5169 err_code |= ERR_ALERT;
5170 goto out;
5171 }
5172
5173 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5174 if (!newuser) {
5175 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5176 err_code |= ERR_ALERT | ERR_ABORT;
5177 goto out;
5178 }
5179
5180 newuser->user = strdup(args[1]);
5181
5182 newuser->next = userlist->users;
5183 userlist->users = newuser;
5184
5185 cur_arg = 2;
5186
5187 while (*args[cur_arg]) {
5188 if (!strcmp(args[cur_arg], "password")) {
5189#ifndef CONFIG_HAP_CRYPT
5190 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5191 file, linenum);
5192 err_code |= ERR_ALERT;
5193#endif
5194 newuser->pass = strdup(args[cur_arg + 1]);
5195 cur_arg += 2;
5196 continue;
5197 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5198 newuser->pass = strdup(args[cur_arg + 1]);
5199 newuser->flags |= AU_O_INSECURE;
5200 cur_arg += 2;
5201 continue;
5202 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005203 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005204 cur_arg += 2;
5205 continue;
5206 } else {
5207 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5208 file, linenum, args[0]);
5209 err_code |= ERR_ALERT | ERR_FATAL;
5210 goto out;
5211 }
5212 }
5213 } else {
5214 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5215 err_code |= ERR_ALERT | ERR_FATAL;
5216 }
5217
5218out:
5219 return err_code;
5220}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221
5222/*
5223 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005224 * Returns the error code, 0 if OK, or any combination of :
5225 * - ERR_ABORT: must abort ASAP
5226 * - ERR_FATAL: we can continue parsing but not start the service
5227 * - ERR_WARN: a warning has been emitted
5228 * - ERR_ALERT: an alert has been emitted
5229 * Only the two first ones can stop processing, the two others are just
5230 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005232int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005234 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 FILE *f;
5236 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005238 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 if ((f=fopen(file,"r")) == NULL)
5241 return -1;
5242
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005243 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005244 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005245 char *end;
5246 char *args[MAX_LINE_ARGS + 1];
5247 char *line = thisline;
5248
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 linenum++;
5250
5251 end = line + strlen(line);
5252
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005253 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5254 /* Check if we reached the limit and the last char is not \n.
5255 * Watch out for the last line without the terminating '\n'!
5256 */
5257 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005258 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005259 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005260 }
5261
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005263 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 line++;
5265
5266 arg = 0;
5267 args[arg] = line;
5268
5269 while (*line && arg < MAX_LINE_ARGS) {
5270 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5271 * C equivalent value. Other combinations left unchanged (eg: \1).
5272 */
5273 if (*line == '\\') {
5274 int skip = 0;
5275 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5276 *line = line[1];
5277 skip = 1;
5278 }
5279 else if (line[1] == 'r') {
5280 *line = '\r';
5281 skip = 1;
5282 }
5283 else if (line[1] == 'n') {
5284 *line = '\n';
5285 skip = 1;
5286 }
5287 else if (line[1] == 't') {
5288 *line = '\t';
5289 skip = 1;
5290 }
5291 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005292 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 unsigned char hex1, hex2;
5294 hex1 = toupper(line[2]) - '0';
5295 hex2 = toupper(line[3]) - '0';
5296 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5297 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5298 *line = (hex1<<4) + hex2;
5299 skip = 3;
5300 }
5301 else {
5302 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005303 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
5305 }
5306 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005307 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 end -= skip;
5309 }
5310 line++;
5311 }
5312 else if (*line == '#' || *line == '\n' || *line == '\r') {
5313 /* end of string, end of loop */
5314 *line = 0;
5315 break;
5316 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005317 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005319 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005320 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 line++;
5322 args[++arg] = line;
5323 }
5324 else {
5325 line++;
5326 }
5327 }
5328
5329 /* empty line */
5330 if (!**args)
5331 continue;
5332
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005333 if (*line) {
5334 /* we had to stop due to too many args.
5335 * Let's terminate the string, print the offending part then cut the
5336 * last arg.
5337 */
5338 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5339 line++;
5340 *line = '\0';
5341
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005342 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005343 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005344 err_code |= ERR_ALERT | ERR_FATAL;
5345 args[arg] = line;
5346 }
5347
Willy Tarreau540abe42007-05-02 20:50:16 +02005348 /* zero out remaining args and ensure that at least one entry
5349 * is zeroed out.
5350 */
5351 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 args[arg] = line;
5353 }
5354
Willy Tarreau3842f002009-06-14 11:39:52 +02005355 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005356 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005357 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005358 for (arg=0; *args[arg+1]; arg++)
5359 args[arg] = args[arg+1]; // shift args after inversion
5360 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005361 else if (!strcmp(args[0], "default")) {
5362 kwm = KWM_DEF;
5363 for (arg=0; *args[arg+1]; arg++)
5364 args[arg] = args[arg+1]; // shift args after inversion
5365 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005366
Willy Tarreau3842f002009-06-14 11:39:52 +02005367 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5368 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005369 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005370 }
5371
Willy Tarreau977b8e42006-12-29 14:19:17 +01005372 if (!strcmp(args[0], "listen") ||
5373 !strcmp(args[0], "frontend") ||
5374 !strcmp(args[0], "backend") ||
5375 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005376 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005378 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005379 cursection = strdup(args[0]);
5380 }
5381 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005383 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005384 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005385 }
5386 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005387 confsect = CFG_USERLIST;
5388 free(cursection);
5389 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005390 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005391 else if (!strcmp(args[0], "peers")) {
5392 confsect = CFG_PEERS;
5393 free(cursection);
5394 cursection = strdup(args[0]);
5395 }
5396
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 /* else it's a section keyword */
5398
5399 switch (confsect) {
5400 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005401 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 break;
5403 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005404 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005406 case CFG_USERLIST:
5407 err_code |= cfg_parse_users(file, linenum, args, kwm);
5408 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005409 case CFG_PEERS:
5410 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5411 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005413 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005414 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005416
5417 if (err_code & ERR_ABORT)
5418 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005420 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005421 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005423 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005424}
5425
Willy Tarreaubb925012009-07-23 13:36:36 +02005426/*
5427 * Returns the error code, 0 if OK, or any combination of :
5428 * - ERR_ABORT: must abort ASAP
5429 * - ERR_FATAL: we can continue parsing but not start the service
5430 * - ERR_WARN: a warning has been emitted
5431 * - ERR_ALERT: an alert has been emitted
5432 * Only the two first ones can stop processing, the two others are just
5433 * indicators.
5434 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005435int check_config_validity()
5436{
5437 int cfgerr = 0;
5438 struct proxy *curproxy = NULL;
5439 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005440 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005441 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005442 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005443
5444 /*
5445 * Now, check for the integrity of all that we have collected.
5446 */
5447
5448 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005449 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005451 /* first, we will invert the proxy list order */
5452 curproxy = NULL;
5453 while (proxy) {
5454 struct proxy *next;
5455
5456 next = proxy->next;
5457 proxy->next = curproxy;
5458 curproxy = proxy;
5459 if (!next)
5460 break;
5461 proxy = next;
5462 }
5463
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005465 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 }
5469
5470 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005471 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005472 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005473 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005474 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005475 unsigned int next_id;
5476
5477 if (!curproxy->uuid) {
5478 /* proxy ID not set, use automatic numbering with first
5479 * spare entry starting with next_pxid.
5480 */
5481 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5482 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5483 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005484 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005485 next_pxid++;
5486
Willy Tarreau55ea7572007-06-17 19:56:27 +02005487
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005489 /* ensure we don't keep listeners uselessly bound */
5490 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 curproxy = curproxy->next;
5492 continue;
5493 }
5494
Willy Tarreauff01a212009-03-15 13:46:16 +01005495 switch (curproxy->mode) {
5496 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005497 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005498 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005499 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5500 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005501 cfgerr++;
5502 }
5503
5504 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005505 Warning("config : servers will be ignored for %s '%s'.\n",
5506 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005507 break;
5508
5509 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005510 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005511 break;
5512
5513 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005514 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005515 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005516 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5517 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005518 cfgerr++;
5519 }
5520 break;
5521 }
5522
5523 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005524 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5525 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005526 cfgerr++;
5527 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005528
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005529 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005530 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005531 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005532 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5533 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005534 cfgerr++;
5535 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005537 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005538 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5539 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005540 cfgerr++;
5541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005543 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005544 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5545 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005546 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005547 }
5548 }
5549 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5550 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5551 /* If no LB algo is set in a backend, and we're not in
5552 * transparent mode, dispatch mode nor proxy mode, we
5553 * want to use balance roundrobin by default.
5554 */
5555 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5556 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 }
5558 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005559
Willy Tarreau82936582007-11-30 15:20:09 +01005560 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5561 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005562 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5563 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005564 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005565 }
5566
Willy Tarreauef781042010-01-27 11:53:01 +01005567 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5568 curproxy->options &= ~PR_O2_CHK_SNDST;
5569 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5570 "send-state", proxy_type_str(curproxy), curproxy->id);
5571 err_code |= ERR_WARN;
5572 }
5573
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005574 /* if a default backend was specified, let's find it */
5575 if (curproxy->defbe.name) {
5576 struct proxy *target;
5577
Alex Williams96532db2009-11-01 21:27:13 -05005578 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005579 if (!target) {
5580 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5581 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005582 cfgerr++;
5583 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005584 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5585 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005586 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005587 } else {
5588 free(curproxy->defbe.name);
5589 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005590 /* we force the backend to be present on at least all of
5591 * the frontend's processes.
5592 */
5593 target->bind_proc = curproxy->bind_proc ?
5594 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 }
5596 }
5597
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005598 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005599 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5600 /* map jump target for ACT_SETBE in req_rep chain */
5601 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005602 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005603 struct proxy *target;
5604
Willy Tarreaua496b602006-12-17 23:15:24 +01005605 if (exp->action != ACT_SETBE)
5606 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005607
Alex Williams96532db2009-11-01 21:27:13 -05005608 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005609 if (!target) {
5610 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5611 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005612 cfgerr++;
5613 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005614 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5615 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005616 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005617 } else {
5618 free((void *)exp->replace);
5619 exp->replace = (const char *)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 Tarreaua496b602006-12-17 23:15:24 +01005625 }
5626 }
5627 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005628
5629 /* find the target proxy for 'use_backend' rules */
5630 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005631 struct proxy *target;
5632
Alex Williams96532db2009-11-01 21:27:13 -05005633 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005634
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005635 if (!target) {
5636 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5637 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005638 cfgerr++;
5639 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005640 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5641 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005642 cfgerr++;
5643 } else {
5644 free((void *)rule->be.name);
5645 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005646 /* we force the backend to be present on at least all of
5647 * the frontend's processes.
5648 */
5649 target->bind_proc = curproxy->bind_proc ?
5650 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005651 }
5652 }
5653
Emeric Brunb982a3d2010-01-04 15:45:53 +01005654 /* find the target table for 'stick' rules */
5655 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5656 struct proxy *target;
5657
Emeric Brun1d33b292010-01-04 15:47:17 +01005658 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5659 if (mrule->flags & STK_IS_STORE)
5660 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5661
Emeric Brunb982a3d2010-01-04 15:45:53 +01005662 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005663 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005664 else
5665 target = curproxy;
5666
5667 if (!target) {
5668 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5669 curproxy->id, mrule->table.name);
5670 cfgerr++;
5671 }
5672 else if (target->table.size == 0) {
5673 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5674 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5675 cfgerr++;
5676 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005677 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005678 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5679 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5680 cfgerr++;
5681 }
5682 else {
5683 free((void *)mrule->table.name);
5684 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005685 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005686 }
5687 }
5688
5689 /* find the target table for 'store response' rules */
5690 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5691 struct proxy *target;
5692
Emeric Brun1d33b292010-01-04 15:47:17 +01005693 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5694
Emeric Brunb982a3d2010-01-04 15:45:53 +01005695 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005696 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005697 else
5698 target = curproxy;
5699
5700 if (!target) {
5701 Alert("Proxy '%s': unable to find store table '%s'.\n",
5702 curproxy->id, mrule->table.name);
5703 cfgerr++;
5704 }
5705 else if (target->table.size == 0) {
5706 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5707 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5708 cfgerr++;
5709 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005710 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005711 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5712 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5713 cfgerr++;
5714 }
5715 else {
5716 free((void *)mrule->table.name);
5717 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005718 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005719 }
5720 }
5721
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005722 /* find the target table for 'tcp-request' layer 4 rules */
5723 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5724 struct proxy *target;
5725
Willy Tarreau56123282010-08-06 19:06:56 +02005726 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005727 continue;
5728
5729 if (trule->act_prm.trk_ctr.table.n)
5730 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5731 else
5732 target = curproxy;
5733
5734 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005735 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5736 curproxy->id, trule->act_prm.trk_ctr.table.n,
5737 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005738 cfgerr++;
5739 }
5740 else if (target->table.size == 0) {
5741 Alert("Proxy '%s': table '%s' used but not configured.\n",
5742 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5743 cfgerr++;
5744 }
5745 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005746 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 +02005747 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5748 cfgerr++;
5749 }
5750 else {
5751 free(trule->act_prm.trk_ctr.table.n);
5752 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005753 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005754 * to pass a list of counters to track and allocate them right here using
5755 * stktable_alloc_data_type().
5756 */
5757 }
5758 }
5759
Willy Tarreaud1f96522010-08-03 19:34:32 +02005760 /* find the target table for 'tcp-request' layer 6 rules */
5761 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5762 struct proxy *target;
5763
Willy Tarreau56123282010-08-06 19:06:56 +02005764 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005765 continue;
5766
5767 if (trule->act_prm.trk_ctr.table.n)
5768 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5769 else
5770 target = curproxy;
5771
5772 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005773 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5774 curproxy->id, trule->act_prm.trk_ctr.table.n,
5775 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005776 cfgerr++;
5777 }
5778 else if (target->table.size == 0) {
5779 Alert("Proxy '%s': table '%s' used but not configured.\n",
5780 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5781 cfgerr++;
5782 }
5783 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005784 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 +02005785 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5786 cfgerr++;
5787 }
5788 else {
5789 free(trule->act_prm.trk_ctr.table.n);
5790 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005791 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005792 * to pass a list of counters to track and allocate them right here using
5793 * stktable_alloc_data_type().
5794 */
5795 }
5796 }
5797
Emeric Brun32da3c42010-09-23 18:39:19 +02005798 if (curproxy->table.peers.name) {
5799 struct peers *curpeers = peers;
5800
5801 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5802 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5803 free((void *)curproxy->table.peers.name);
5804 curproxy->table.peers.p = peers;
5805 break;
5806 }
5807 }
5808
5809 if (!curpeers) {
5810 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5811 curproxy->id, curproxy->table.peers.name);
5812 cfgerr++;
5813 }
5814 else if (!curpeers->peers_fe) {
5815 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5816 curproxy->id, curpeers->id);
5817 cfgerr++;
5818 }
5819 }
5820
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005821 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5822 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005823 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5824 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5825 "proxy", curproxy->id);
5826 cfgerr++;
5827 goto out_uri_auth_compat;
5828 }
5829
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005830 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005831 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005832 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005833 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005834
Willy Tarreau95fa4692010-02-01 13:05:50 +01005835 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5836 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005837
5838 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005839 uri_auth_compat_req[i++] = "realm";
5840 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5841 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005842
Willy Tarreau95fa4692010-02-01 13:05:50 +01005843 uri_auth_compat_req[i++] = "unless";
5844 uri_auth_compat_req[i++] = "{";
5845 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5846 uri_auth_compat_req[i++] = "}";
5847 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005848
Willy Tarreau95fa4692010-02-01 13:05:50 +01005849 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5850 if (!req_acl) {
5851 cfgerr++;
5852 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005853 }
5854
Willy Tarreau95fa4692010-02-01 13:05:50 +01005855 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5856
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005857 if (curproxy->uri_auth->auth_realm) {
5858 free(curproxy->uri_auth->auth_realm);
5859 curproxy->uri_auth->auth_realm = NULL;
5860 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005861
5862 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005863 }
5864out_uri_auth_compat:
5865
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005866 cfgerr += acl_find_targets(curproxy);
5867
Willy Tarreau2738a142006-07-08 17:28:09 +02005868 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005869 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005870 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005871 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005872 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005873 " | While not properly invalid, you will certainly encounter various problems\n"
5874 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005875 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005876 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005877 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005878 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005879
Willy Tarreau1fa31262007-12-03 00:36:16 +01005880 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5881 * We must still support older configurations, so let's find out whether those
5882 * parameters have been set or must be copied from contimeouts.
5883 */
5884 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005885 if (!curproxy->timeout.tarpit ||
5886 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005887 /* tarpit timeout not set. We search in the following order:
5888 * default.tarpit, curr.connect, default.connect.
5889 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005890 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005891 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005892 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005893 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005894 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005895 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005896 }
5897 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005898 (!curproxy->timeout.queue ||
5899 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005900 /* queue timeout not set. We search in the following order:
5901 * default.queue, curr.connect, default.connect.
5902 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005903 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005904 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005905 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005906 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005907 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005908 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005909 }
5910 }
5911
Willy Tarreau07a54902010-03-29 18:33:29 +02005912 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005913 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5914 curproxy->check_req = (char *)malloc(curproxy->check_len);
5915 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005916 }
5917
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005918 /* The small pools required for the capture lists */
5919 if (curproxy->nb_req_cap)
5920 curproxy->req_cap_pool = create_pool("ptrcap",
5921 curproxy->nb_req_cap * sizeof(char *),
5922 MEM_F_SHARED);
5923 if (curproxy->nb_rsp_cap)
5924 curproxy->rsp_cap_pool = create_pool("ptrcap",
5925 curproxy->nb_rsp_cap * sizeof(char *),
5926 MEM_F_SHARED);
5927
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005928 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5929 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5930 MEM_F_SHARED);
5931
Willy Tarreau86034312006-12-29 00:10:33 +01005932 /* for backwards compatibility with "listen" instances, if
5933 * fullconn is not set but maxconn is set, then maxconn
5934 * is used.
5935 */
5936 if (!curproxy->fullconn)
5937 curproxy->fullconn = curproxy->maxconn;
5938
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939 /* first, we will invert the servers list order */
5940 newsrv = NULL;
5941 while (curproxy->srv) {
5942 struct server *next;
5943
5944 next = curproxy->srv->next;
5945 curproxy->srv->next = newsrv;
5946 newsrv = curproxy->srv;
5947 if (!next)
5948 break;
5949 curproxy->srv = next;
5950 }
5951
Willy Tarreaudd701652010-05-25 23:03:02 +02005952 /* assign automatic UIDs to servers which don't have one yet */
5953 next_id = 1;
5954 newsrv = curproxy->srv;
5955 while (newsrv != NULL) {
5956 if (!newsrv->puid) {
5957 /* server ID not set, use automatic numbering with first
5958 * spare entry starting with next_svid.
5959 */
5960 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5961 newsrv->conf.id.key = newsrv->puid = next_id;
5962 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5963 }
5964 next_id++;
5965 newsrv = newsrv->next;
5966 }
5967
Willy Tarreau20697042007-11-15 23:26:18 +01005968 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005969 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005971 /* We have to initialize the server lookup mechanism depending
5972 * on what LB algorithm was choosen.
5973 */
5974
5975 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5976 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5977 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005978 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5979 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5980 init_server_map(curproxy);
5981 } else {
5982 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5983 fwrr_init_server_groups(curproxy);
5984 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005985 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005986
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005987 case BE_LB_KIND_LC:
5988 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005989 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005990 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005991
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005992 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005993 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5994 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5995 chash_init_server_tree(curproxy);
5996 } else {
5997 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5998 init_server_map(curproxy);
5999 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006000 break;
6001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006002
6003 if (curproxy->options & PR_O_LOGASAP)
6004 curproxy->to_log &= ~LW_BYTES;
6005
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006006 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6007 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6008 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6009 proxy_type_str(curproxy), curproxy->id);
6010 err_code |= ERR_WARN;
6011 }
6012
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006013 if (curproxy->mode != PR_MODE_HTTP) {
6014 int optnum;
6015
6016 if (curproxy->options & PR_O_COOK_ANY) {
6017 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6018 proxy_type_str(curproxy), curproxy->id);
6019 err_code |= ERR_WARN;
6020 }
6021
6022 if (curproxy->uri_auth) {
6023 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6024 proxy_type_str(curproxy), curproxy->id);
6025 err_code |= ERR_WARN;
6026 curproxy->uri_auth = NULL;
6027 }
6028
6029 if (curproxy->options & PR_O_FWDFOR) {
6030 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6031 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6032 err_code |= ERR_WARN;
6033 curproxy->options &= ~PR_O_FWDFOR;
6034 }
6035
6036 if (curproxy->options & PR_O_ORGTO) {
6037 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6038 "originalto", proxy_type_str(curproxy), curproxy->id);
6039 err_code |= ERR_WARN;
6040 curproxy->options &= ~PR_O_ORGTO;
6041 }
6042
6043 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6044 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6045 (curproxy->cap & cfg_opts[optnum].cap) &&
6046 (curproxy->options & cfg_opts[optnum].val)) {
6047 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6048 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6049 err_code |= ERR_WARN;
6050 curproxy->options &= ~cfg_opts[optnum].val;
6051 }
6052 }
6053
6054 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6055 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6056 (curproxy->cap & cfg_opts2[optnum].cap) &&
6057 (curproxy->options2 & cfg_opts2[optnum].val)) {
6058 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6059 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6060 err_code |= ERR_WARN;
6061 curproxy->options2 &= ~cfg_opts2[optnum].val;
6062 }
6063 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006064
Willy Tarreauefa5f512010-03-30 20:13:29 +02006065#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006066 if (curproxy->bind_hdr_occ) {
6067 curproxy->bind_hdr_occ = 0;
6068 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6069 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6070 err_code |= ERR_WARN;
6071 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006072#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006073 }
6074
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006076 * ensure that we're not cross-dressing a TCP server into HTTP.
6077 */
6078 newsrv = curproxy->srv;
6079 while (newsrv != NULL) {
6080 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006081 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6082 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006083 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006084 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006085
Willy Tarreauefa5f512010-03-30 20:13:29 +02006086#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006087 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6088 newsrv->bind_hdr_occ = 0;
6089 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6090 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6091 err_code |= ERR_WARN;
6092 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006093#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006094 newsrv = newsrv->next;
6095 }
6096
6097 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 * If this server supports a maxconn parameter, it needs a dedicated
6099 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006100 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101 */
6102 newsrv = curproxy->srv;
6103 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006104 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 /* Only 'minconn' was specified, or it was higher than or equal
6106 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6107 * this will avoid further useless expensive computations.
6108 */
6109 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006110 } else if (newsrv->maxconn && !newsrv->minconn) {
6111 /* minconn was not specified, so we set it to maxconn */
6112 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006113 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006114 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6115 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006116 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006117 }
6118
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006119 if (newsrv->trackit) {
6120 struct proxy *px;
6121 struct server *srv;
6122 char *pname, *sname;
6123
6124 pname = newsrv->trackit;
6125 sname = strrchr(pname, '/');
6126
6127 if (sname)
6128 *sname++ = '\0';
6129 else {
6130 sname = pname;
6131 pname = NULL;
6132 }
6133
6134 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006135 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006136 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006137 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6138 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006139 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006140 cfgerr++;
6141 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006142 }
6143 } else
6144 px = curproxy;
6145
6146 srv = findserver(px, sname);
6147 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006148 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6149 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006150 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006151 cfgerr++;
6152 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006153 }
6154
6155 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006156 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006157 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006158 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006159 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006160 cfgerr++;
6161 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006162 }
6163
6164 if (curproxy != px &&
6165 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006166 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006167 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006168 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006169 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006170 cfgerr++;
6171 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006172 }
6173
6174 newsrv->tracked = srv;
6175 newsrv->tracknext = srv->tracknext;
6176 srv->tracknext = newsrv;
6177
6178 free(newsrv->trackit);
6179 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006180 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 newsrv = newsrv->next;
6182 }
6183
Willy Tarreauc1a21672009-08-16 22:37:44 +02006184 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006185 curproxy->accept = frontend_accept;
6186
Willy Tarreauc1a21672009-08-16 22:37:44 +02006187 if (curproxy->tcp_req.inspect_delay ||
6188 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006189 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006190
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006191 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006192 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006193 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006194 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006195
6196 /* both TCP and HTTP must check switching rules */
6197 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6198 }
6199
6200 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006201 if (curproxy->tcp_req.inspect_delay ||
6202 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6203 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6204
Emeric Brun97679e72010-09-23 17:56:44 +02006205 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6206 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6207
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006208 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006209 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006210 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006211 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006212
6213 /* If the backend does requires RDP cookie persistence, we have to
6214 * enable the corresponding analyser.
6215 */
6216 if (curproxy->options2 & PR_O2_RDPC_PRST)
6217 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6218 }
6219
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006220 listener = NULL;
6221 while (curproxy->listen) {
6222 struct listener *next;
6223
6224 next = curproxy->listen->next;
6225 curproxy->listen->next = listener;
6226 listener = curproxy->listen;
6227
6228 if (!next)
6229 break;
6230
6231 curproxy->listen = next;
6232 }
6233
Willy Tarreaue6b98942007-10-29 01:09:36 +01006234 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006235 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006236 listener = curproxy->listen;
6237 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006238 if (!listener->luid) {
6239 /* listener ID not set, use automatic numbering with first
6240 * spare entry starting with next_luid.
6241 */
6242 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6243 listener->conf.id.key = listener->luid = next_id;
6244 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006245 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006246 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006247
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006248 /* enable separate counters */
6249 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6250 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6251 if (!listener->name) {
6252 sprintf(trash, "sock-%d", listener->luid);
6253 listener->name = strdup(trash);
6254 }
6255 }
6256
Willy Tarreaue6b98942007-10-29 01:09:36 +01006257 if (curproxy->options & PR_O_TCP_NOLING)
6258 listener->options |= LI_O_NOLINGER;
6259 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006260 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006261 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006262 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006263 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006264 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006265 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006266
Willy Tarreau8a956912010-10-15 14:27:08 +02006267 if (listener->options & LI_O_ACC_PROXY)
6268 listener->analysers |= AN_REQ_DECODE_PROXY;
6269
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006270 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6271 listener->options |= LI_O_TCP_RULES;
6272
Willy Tarreaude3041d2010-05-31 10:56:17 +02006273 if (curproxy->mon_mask.s_addr)
6274 listener->options |= LI_O_CHK_MONNET;
6275
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006276 /* smart accept mode is automatic in HTTP mode */
6277 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6278 (curproxy->mode == PR_MODE_HTTP &&
6279 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6280 listener->options |= LI_O_NOQUICKACK;
6281
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006282 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006283 listener = listener->next;
6284 }
6285
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006286 /* Check multi-process mode compatibility for the current proxy */
6287 if (global.nbproc > 1) {
6288 int nbproc = 0;
6289 if (curproxy->bind_proc) {
6290 int proc;
6291 for (proc = 0; proc < global.nbproc; proc++) {
6292 if (curproxy->bind_proc & (1 << proc)) {
6293 nbproc++;
6294 }
6295 }
6296 } else {
6297 nbproc = global.nbproc;
6298 }
6299 if (curproxy->table.peers.name) {
6300 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6301 curproxy->id);
6302 cfgerr++;
6303 }
6304 if (nbproc > 1) {
6305 if (curproxy->uri_auth) {
6306 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6307 curproxy->id);
6308 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6309 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6310 curproxy->id);
6311 }
6312 }
6313 if (curproxy->appsession_name) {
6314 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6315 curproxy->id);
6316 }
6317 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6318 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6319 curproxy->id);
6320 }
6321 }
6322 }
6323
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 curproxy = curproxy->next;
6325 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006326
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006327 /* Check multi-process mode compatibility */
6328 if (global.nbproc > 1) {
6329 if (global.stats_fe) {
6330 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6331 }
6332 }
6333
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006334 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6335 struct auth_users *curuser;
6336 int g;
6337
6338 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6339 unsigned int group_mask = 0;
6340 char *group = NULL;
6341
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006342 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006343 continue;
6344
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006345 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006346
6347 for (g = 0; g < curuserlist->grpcnt; g++)
6348 if (!strcmp(curuserlist->groups[g], group))
6349 break;
6350
6351 if (g == curuserlist->grpcnt) {
6352 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6353 curuserlist->name, group, curuser->user);
6354 err_code |= ERR_ALERT | ERR_FATAL;
6355 goto out;
6356 }
6357
6358 group_mask |= (1 << g);
6359 }
6360
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006361 free(curuser->u.groups);
6362 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006363 }
6364
6365 for (g = 0; g < curuserlist->grpcnt; g++) {
6366 char *user = NULL;
6367
6368 if (!curuserlist->groupusers[g])
6369 continue;
6370
6371 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6372 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6373 if (!strcmp(curuser->user, user))
6374 break;
6375
6376 if (!curuser) {
6377 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6378 curuserlist->name, user, curuserlist->groups[g]);
6379 err_code |= ERR_ALERT | ERR_FATAL;
6380 goto out;
6381 }
6382
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006383 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006384 }
6385
6386 free(curuserlist->groupusers[g]);
6387 }
6388
6389 free(curuserlist->groupusers);
6390
6391#ifdef DEBUG_AUTH
6392 for (g = 0; g < curuserlist->grpcnt; g++) {
6393 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6394
6395 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6396 if (curuser->group_mask & (1 << g))
6397 fprintf(stderr, " %s", curuser->user);
6398 }
6399
6400 fprintf(stderr, "\n");
6401 }
6402#endif
6403
6404 }
6405
Willy Tarreau056f5682010-06-06 15:51:11 +02006406 /* initialize stick-tables on backend capable proxies. This must not
6407 * be done earlier because the data size may be discovered while parsing
6408 * other proxies.
6409 */
6410 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006411 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006412
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006413 /*
6414 * Recount currently required checks.
6415 */
6416
6417 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6418 int optnum;
6419
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006420 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6421 if (curproxy->options & cfg_opts[optnum].val)
6422 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006423
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006424 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6425 if (curproxy->options2 & cfg_opts2[optnum].val)
6426 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006427 }
6428
Willy Tarreaubb925012009-07-23 13:36:36 +02006429 if (cfgerr > 0)
6430 err_code |= ERR_ALERT | ERR_FATAL;
6431 out:
6432 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433}
6434
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006435/*
6436 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6437 * parsing sessions.
6438 */
6439void cfg_register_keywords(struct cfg_kw_list *kwl)
6440{
6441 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6442}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006444/*
6445 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6446 */
6447void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6448{
6449 LIST_DEL(&kwl->list);
6450 LIST_INIT(&kwl->list);
6451}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452
6453/*
6454 * Local variables:
6455 * c-indent-level: 8
6456 * c-basic-offset: 8
6457 * End:
6458 */