blob: aae2efeda193273f17d61115799a818e97ef918b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010047#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
189 char *c, *next, *range, *dupstr;
190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
210 Alert("Socket path '%s' too long (max %d)\n", str, max_path_len);
211 goto fail;
212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200215 ss.ss_family = AF_UNIX;
216 if (global.unix_bind.prefix) {
217 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
218 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 }
Emeric Bruned760922010-10-22 17:59:25 +0200220 else {
221 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
222 }
223 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 }
225 else {
Emeric Bruned760922010-10-22 17:59:25 +0200226 /* 2) look for the addr/port delimiter, it's the last colon. */
227 if ((range = strrchr(str, ':')) == NULL) {
228 Alert("Missing port number: '%s'\n", str);
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231
232 *range++ = 0;
233
234 if (strrchr(str, ':') != NULL) {
235 /* IPv6 address contains ':' */
236 memset(&ss, 0, sizeof(ss));
237 ss.ss_family = AF_INET6;
238
239 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
240 Alert("Invalid server address: '%s'\n", str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Emeric Bruned760922010-10-22 17:59:25 +0200244 else {
245 memset(&ss, 0, sizeof(ss));
246 ss.ss_family = AF_INET;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Emeric Bruned760922010-10-22 17:59:25 +0200248 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
249 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
250 }
251 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
252 struct hostent *he;
253
254 if ((he = gethostbyname(str)) == NULL) {
255 Alert("Invalid server name: '%s'\n", str);
256 goto fail;
257 }
258 else
259 ((struct sockaddr_in *)&ss)->sin_addr =
260 *(struct in_addr *) *(he->h_addr_list);
261 }
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Emeric Bruned760922010-10-22 17:59:25 +0200264 /* 3) look for the port-end delimiter */
265 if ((c = strchr(range, '-')) != NULL) {
266 *c++ = 0;
267 end = atol(c);
268 }
269 else {
270 end = atol(range);
271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
Emeric Bruned760922010-10-22 17:59:25 +0200273 port = atol(range);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
Emeric Bruned760922010-10-22 17:59:25 +0200275 if (port < 1 || port > 65535) {
276 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
277 goto fail;
278 }
279
280 if (end < 1 || end > 65535) {
281 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
282 goto fail;
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 }
285
286 for (; port <= end; port++) {
287 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 l->next = curproxy->listen;
289 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
291 l->fd = -1;
292 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 l->state = LI_INIT;
294
Emeric Bruned760922010-10-22 17:59:25 +0200295 if(ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100297 tcpv4_add_listener(l);
298 }
Emeric Bruned760922010-10-22 17:59:25 +0200299 else if (ss.ss_family == AF_INET6) {
300 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
301 tcpv6_add_listener(l);
302 }
303 else {
304 l->perm.ux.gid = l->perm.ux.uid = -1;
305 l->perm.ux.mode = 0;
306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320/*
321 * Sends a warning if proxy <proxy> does not have at least one of the
322 * capabilities in <cap>. An optionnal <hint> may be added at the end
323 * of the warning to help the user. Returns 1 if a warning was emitted
324 * or 0 if the condition is valid.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100327{
328 char *msg;
329
330 switch (cap) {
331 case PR_CAP_BE: msg = "no backend"; break;
332 case PR_CAP_FE: msg = "no frontend"; break;
333 case PR_CAP_RS: msg = "no ruleset"; break;
334 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
335 default: msg = "not enough"; break;
336 }
337
338 if (!(proxy->cap & cap)) {
339 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100340 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100341 return 1;
342 }
343 return 0;
344}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345
Willy Tarreau61d18892009-03-31 10:49:21 +0200346/* Report a warning if a rule is placed after a 'block' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (!LIST_ISEMPTY(&proxy->block_cond)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
415 warnif_rule_after_reqadd(proxy, file, line, arg) ||
416 warnif_rule_after_redirect(proxy, file, line, arg) ||
417 warnif_rule_after_use_backend(proxy, file, line, arg);
418}
419
420/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100421int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200422{
423 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
424 warnif_rule_after_redirect(proxy, file, line, arg) ||
425 warnif_rule_after_use_backend(proxy, file, line, arg);
426}
427
428/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 return warnif_rule_after_redirect(proxy, file, line, arg) ||
432 warnif_rule_after_use_backend(proxy, file, line, arg);
433}
434
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100435/* Report it if a request ACL condition uses some response-only parameters. It
436 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
447 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100452/* Report it if a request ACL condition uses some request-only volatile parameters.
453 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
454 * Note that <cond> may be NULL and then will be ignored.
455 */
456static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
457{
458 struct acl *acl;
459
460 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
461 return 0;
462
463 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
464 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
465 file, line, acl ? acl->name : "(unknown)");
466 return ERR_WARN;
467}
468
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100469
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 * parse a line in a <global> section. Returns the error code, 0 if OK, or
472 * any combination of :
473 * - ERR_ABORT: must abort ASAP
474 * - ERR_FATAL: we can continue parsing but not start the service
475 * - ERR_WARN: a warning has been emitted
476 * - ERR_ALERT: an alert has been emitted
477 * Only the two first ones can stop processing, the two others are just
478 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200480int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481{
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483
484 if (!strcmp(args[0], "global")) { /* new section */
485 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 }
488 else if (!strcmp(args[0], "daemon")) {
489 global.mode |= MODE_DAEMON;
490 }
491 else if (!strcmp(args[0], "debug")) {
492 global.mode |= MODE_DEBUG;
493 }
494 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100495 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200497 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100498 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200499 }
500 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100501 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100504 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100506 else if (!strcmp(args[0], "nosplice")) {
507 global.tune.options &= ~GTUNE_USE_SPLICE;
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "quiet")) {
510 global.mode |= MODE_QUIET;
511 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200512 else if (!strcmp(args[0], "tune.maxpollevents")) {
513 if (global.tune.maxpollevents != 0) {
514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT;
516 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200517 }
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200522 }
523 global.tune.maxpollevents = atol(args[1]);
524 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100525 else if (!strcmp(args[0], "tune.maxaccept")) {
526 if (global.tune.maxaccept != 0) {
527 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200528 err_code |= ERR_ALERT;
529 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100530 }
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100535 }
536 global.tune.maxaccept = atol(args[1]);
537 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200538 else if (!strcmp(args[0], "tune.chksize")) {
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT | ERR_FATAL;
542 goto out;
543 }
544 global.tune.chksize = atol(args[1]);
545 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200546 else if (!strcmp(args[0], "tune.bufsize")) {
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.bufsize = atol(args[1]);
553 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
554 global.tune.maxrewrite = global.tune.bufsize / 2;
555 }
556 else if (!strcmp(args[0], "tune.maxrewrite")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.maxrewrite = atol(args[1]);
563 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
564 global.tune.maxrewrite = global.tune.bufsize / 2;
565 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100566 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
567 if (global.tune.client_rcvbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_rcvbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
580 if (global.tune.server_rcvbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_rcvbuf = atol(args[1]);
591 }
592 else if (!strcmp(args[0], "tune.sndbuf.client")) {
593 if (global.tune.client_sndbuf != 0) {
594 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT;
596 goto out;
597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.client_sndbuf = atol(args[1]);
604 }
605 else if (!strcmp(args[0], "tune.sndbuf.server")) {
606 if (global.tune.server_sndbuf != 0) {
607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT;
609 goto out;
610 }
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.server_sndbuf = atol(args[1]);
617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 else if (!strcmp(args[0], "uid")) {
619 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 global.uid = atol(args[1]);
630 }
631 else if (!strcmp(args[0], "gid")) {
632 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.gid = atol(args[1]);
643 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 /* user/group name handling */
645 else if (!strcmp(args[0], "user")) {
646 struct passwd *ha_user;
647 if (global.uid != 0) {
648 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 errno = 0;
653 ha_user = getpwnam(args[1]);
654 if (ha_user != NULL) {
655 global.uid = (int)ha_user->pw_uid;
656 }
657 else {
658 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 }
662 else if (!strcmp(args[0], "group")) {
663 struct group *ha_group;
664 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200665 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 errno = 0;
670 ha_group = getgrnam(args[1]);
671 if (ha_group != NULL) {
672 global.gid = (int)ha_group->gr_gid;
673 }
674 else {
675 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200677 }
678 }
679 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nbproc")) {
681 if (global.nbproc != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 global.nbproc = atol(args[1]);
692 }
693 else if (!strcmp(args[0], "maxconn")) {
694 if (global.maxconn != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.maxconn = atol(args[1]);
705#ifdef SYSTEM_MAXCONN
706 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
707 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
708 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711#endif /* SYSTEM_MAXCONN */
712 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100713 else if (!strcmp(args[0], "maxpipes")) {
714 if (global.maxpipes != 0) {
715 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200716 err_code |= ERR_ALERT;
717 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100718 }
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100723 }
724 global.maxpipes = atol(args[1]);
725 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 else if (!strcmp(args[0], "ulimit-n")) {
727 if (global.rlimit_nofile != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 global.rlimit_nofile = atol(args[1]);
738 }
739 else if (!strcmp(args[0], "chroot")) {
740 if (global.chroot != NULL) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.chroot = strdup(args[1]);
751 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200752 else if (!strcmp(args[0], "description")) {
753 int i, len=0;
754 char *d;
755
756 if (!*args[1]) {
757 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
758 file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762
763 for(i=1; *args[i]; i++)
764 len += strlen(args[i])+1;
765
766 if (global.desc)
767 free(global.desc);
768
769 global.desc = d = (char *)calloc(1, len);
770
771 d += sprintf(d, "%s", args[1]);
772 for(i=2; *args[i]; i++)
773 d += sprintf(d, " %s", args[i]);
774 }
775 else if (!strcmp(args[0], "node")) {
776 int i;
777 char c;
778
779 for (i=0; args[1][i]; i++) {
780 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100781 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
782 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200783 break;
784 }
785
786 if (!i || args[1][i]) {
787 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
788 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793
794 if (global.node)
795 free(global.node);
796
797 global.node = strdup(args[1]);
798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 else if (!strcmp(args[0], "pidfile")) {
800 if (global.pidfile != NULL) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 global.pidfile = strdup(args[1]);
811 }
Emeric Bruned760922010-10-22 17:59:25 +0200812 else if (!strcmp(args[0], "unix-bind")) {
813 int cur_arg = 1;
814 while (*(args[cur_arg])) {
815 if (!strcmp(args[cur_arg], "prefix")) {
816 if (global.unix_bind.prefix != NULL) {
817 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
818 err_code |= ERR_ALERT;
819 cur_arg += 2;
820 continue;
821 }
822
823 if (*(args[cur_arg+1]) == 0) {
824 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.unix_bind.prefix = strdup(args[cur_arg+1]);
829 cur_arg += 2;
830 continue;
831 }
832
833 if (!strcmp(args[cur_arg], "mode")) {
834
835 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
836 cur_arg += 2;
837 continue;
838 }
839
840 if (!strcmp(args[cur_arg], "uid")) {
841
842 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
843 cur_arg += 2;
844 continue;
845 }
846
847 if (!strcmp(args[cur_arg], "gid")) {
848
849 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
850 cur_arg += 2;
851 continue;
852 }
853
854 if (!strcmp(args[cur_arg], "user")) {
855 struct passwd *user;
856
857 user = getpwnam(args[cur_arg + 1]);
858 if (!user) {
859 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
860 file, linenum, args[0], args[cur_arg + 1 ]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864
865 global.unix_bind.ux.uid = user->pw_uid;
866 cur_arg += 2;
867 continue;
868 }
869
870 if (!strcmp(args[cur_arg], "group")) {
871 struct group *group;
872
873 group = getgrnam(args[cur_arg + 1]);
874 if (!group) {
875 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
876 file, linenum, args[0], args[cur_arg + 1 ]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880
881 global.unix_bind.ux.gid = group->gr_gid;
882 cur_arg += 2;
883 continue;
884 }
885
886 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
887 file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100893 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200894 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895
896 if (*(args[1]) == 0 || *(args[2]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901
902 facility = get_log_facility(args[2]);
903 if (facility < 0) {
904 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200905 err_code |= ERR_ALERT | ERR_FATAL;
906 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907 }
908
909 level = 7; /* max syslog level = debug */
910 if (*(args[3])) {
911 level = get_log_level(args[3]);
912 if (level < 0) {
913 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200914 err_code |= ERR_ALERT | ERR_FATAL;
915 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 }
917 }
918
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200919 minlvl = 0; /* limit syslog level to this level (emerg) */
920 if (*(args[4])) {
921 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200923 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
925 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 }
927 }
928
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100930 struct sockaddr_un *sk = str2sun(args[1]);
931 if (!sk) {
932 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
933 args[1], (int)sizeof(sk->sun_path) - 1);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100938 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100939 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100940 struct sockaddr_in *sk = str2sa(args[1]);
941 if (!sk) {
942 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100947 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100948 if (!logsrv.u.in.sin_port)
949 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951
952 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100953 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 global.logfac1 = facility;
955 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200956 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 global.logfac2 = facility;
961 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200962 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 else {
965 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200968 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100969 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
970 char *name;
971 int len;
972
973 if (global.log_send_hostname != NULL) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT;
976 goto out;
977 }
978
979 if (*(args[1]))
980 name = args[1];
981 else
982 name = hostname;
983
984 len = strlen(name);
985
986 /* We'll add a space after the name to respect the log format */
987 free(global.log_send_hostname);
988 global.log_send_hostname = malloc(len + 2);
989 snprintf(global.log_send_hostname, len + 2, "%s ", name);
990 }
Kevinm48936af2010-12-22 16:08:21 +0000991 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
992 if (*(args[1]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
994 err_code |= ERR_ALERT | ERR_FATAL;
995 goto out;
996 }
997 free(global.log_tag);
998 global.log_tag = strdup(args[1]);
999 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001000 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1001 if (global.spread_checks != 0) {
1002 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT;
1004 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 }
1006 if (*(args[1]) == 0) {
1007 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 global.spread_checks = atol(args[1]);
1012 if (global.spread_checks < 0 || global.spread_checks > 50) {
1013 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
1017 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001018 struct cfg_kw_list *kwl;
1019 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001020 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001021
1022 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1023 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1024 if (kwl->kw[index].section != CFG_GLOBAL)
1025 continue;
1026 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1027 /* prepare error message just in case */
1028 snprintf(trash, sizeof(trash),
1029 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1031 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001032 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001033 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001034 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 else if (rc > 0) {
1036 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_WARN;
1038 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001039 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001041 }
1042 }
1043 }
1044
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001048
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 out:
1050 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051}
1052
Willy Tarreau97cb7802010-01-03 20:23:58 +01001053/* Perform the most basic initialization of a proxy :
1054 * memset(), list_init(*), reset_timeouts(*).
1055 */
1056static void init_new_proxy(struct proxy *p)
1057{
1058 memset(p, 0, sizeof(struct proxy));
1059 LIST_INIT(&p->pendconns);
1060 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001061 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001062 LIST_INIT(&p->block_cond);
1063 LIST_INIT(&p->redirect_rules);
1064 LIST_INIT(&p->mon_fail_cond);
1065 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001066 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001067 LIST_INIT(&p->sticking_rules);
1068 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001069 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001070 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001071 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001072 LIST_INIT(&p->req_add);
1073 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001074
1075 /* Timeouts are defined as -1 */
1076 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001077 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001078}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001080void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001082 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 defproxy.mode = PR_MODE_TCP;
1084 defproxy.state = PR_STNEW;
1085 defproxy.maxconn = cfg_maxpconn;
1086 defproxy.conn_retries = CONN_RETRIES;
1087 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001088
1089 defproxy.defsrv.inter = DEF_CHKINTR;
1090 defproxy.defsrv.fastinter = 0;
1091 defproxy.defsrv.downinter = 0;
1092 defproxy.defsrv.rise = DEF_RISETIME;
1093 defproxy.defsrv.fall = DEF_FALLTIME;
1094 defproxy.defsrv.check_port = 0;
1095 defproxy.defsrv.maxqueue = 0;
1096 defproxy.defsrv.minconn = 0;
1097 defproxy.defsrv.maxconn = 0;
1098 defproxy.defsrv.slowstart = 0;
1099 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1100 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1101 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102}
1103
Willy Tarreauade5ec42010-01-28 19:33:49 +01001104
1105static int create_cond_regex_rule(const char *file, int line,
1106 struct proxy *px, int dir, int action, int flags,
1107 const char *cmd, const char *reg, const char *repl,
1108 const char **cond_start)
1109{
1110 regex_t *preg = NULL;
1111 const char *err;
1112 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001113 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114
1115 if (px == &defproxy) {
1116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto err;
1119 }
1120
1121 if (*reg == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1128 err_code |= ERR_WARN;
1129
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 if (cond_start &&
1131 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1132 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1133 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1134 file, line, cmd);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138 }
1139 else if (cond_start && **cond_start) {
1140 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1141 file, line, cmd, *cond_start);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto err;
1144 }
1145
1146 if (dir == ACL_DIR_REQ)
1147 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001148 else
1149 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001150
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 preg = calloc(1, sizeof(regex_t));
1152 if (!preg) {
1153 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1154 err_code = ERR_ALERT | ERR_FATAL;
1155 goto err;
1156 }
1157
1158 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1159 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1160 err_code = ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
1164 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001165 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 if (repl && err) {
1167 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1168 file, line, cmd, *err);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto err;
1171 }
1172
1173 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1174 err_code |= ERR_WARN;
1175
1176 return err_code;
1177 err:
1178 free(preg);
1179 return err_code;
1180}
1181
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001184 * Returns the error code, 0 if OK, or any combination of :
1185 * - ERR_ABORT: must abort ASAP
1186 * - ERR_FATAL: we can continue parsing but not start the service
1187 * - ERR_WARN: a warning has been emitted
1188 * - ERR_ALERT: an alert has been emitted
1189 * Only the two first ones can stop processing, the two others are just
1190 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001192int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1193{
1194 static struct peers *curpeers = NULL;
1195 struct peer *newpeer = NULL;
1196 const char *err;
1197 int err_code = 0;
1198
1199 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1200
1201 err = invalid_char(args[1]);
1202 if (err) {
1203 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1204 file, linenum, *err, args[0], args[1]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 }
1207
1208 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1209 /*
1210 * If there are two proxies with the same name only following
1211 * combinations are allowed:
1212 */
1213 if (strcmp(curpeers->id, args[1]) == 0) {
1214 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1215 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1216 err_code |= ERR_WARN;
1217 }
1218 }
1219
1220 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1221 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1222 err_code |= ERR_ALERT | ERR_ABORT;
1223 goto out;
1224 }
1225
1226 curpeers->next = peers;
1227 peers = curpeers;
1228 curpeers->conf.file = file;
1229 curpeers->conf.line = linenum;
1230 curpeers->last_change = now.tv_sec;
1231 curpeers->id = strdup(args[1]);
1232 }
1233 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1234 char *rport, *raddr;
1235 short realport = 0;
1236 struct sockaddr_in *sk;
1237
1238 if (!*args[2]) {
1239 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1240 file, linenum, args[0]);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244
1245 err = invalid_char(args[1]);
1246 if (err) {
1247 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1248 file, linenum, *err, args[1]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252
1253 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1254 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1255 err_code |= ERR_ALERT | ERR_ABORT;
1256 goto out;
1257 }
1258
1259 /* the peers are linked backwards first */
1260 curpeers->count++;
1261 newpeer->next = curpeers->remote;
1262 curpeers->remote = newpeer;
1263 newpeer->peers = curpeers;
1264 newpeer->conf.file = file;
1265 newpeer->conf.line = linenum;
1266
1267 newpeer->last_change = now.tv_sec;
1268 newpeer->id = strdup(args[1]);
1269
1270 raddr = strdup(args[2]);
1271 rport = strchr(raddr, ':');
1272 if (rport) {
1273 *rport++ = 0;
1274 realport = atol(rport);
1275 }
1276 if (!realport) {
1277 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
1281
1282 sk = str2sa(raddr);
1283 free(raddr);
1284 if (!sk) {
1285 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 newpeer->addr = *sk;
1290 newpeer->addr.sin_port = htons(realport);
1291
1292 if (strcmp(newpeer->id, localpeer) == 0) {
1293 /* Current is local peer, it define a frontend */
1294 newpeer->local = 1;
1295
1296 if (!curpeers->peers_fe) {
1297 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1299 err_code |= ERR_ALERT | ERR_ABORT;
1300 goto out;
1301 }
1302 curpeers->peers_fe->parent = curpeers;
1303
1304 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1305 LIST_INIT(&(curpeers->peers_fe)->acl);
1306 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1307 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1308 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1309 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1310 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1311 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1312
1313 proxy_reset_timeouts(curpeers->peers_fe);
1314
1315 curpeers->peers_fe->last_change = now.tv_sec;
1316 curpeers->peers_fe->id = strdup(args[1]);
1317 curpeers->peers_fe->cap = PR_CAP_FE;
1318 curpeers->peers_fe->maxconn = 65000;
1319 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1320 curpeers->peers_fe->timeout.connect = 5000;
1321 curpeers->peers_fe->accept = peer_accept;
1322 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1323 if (!str2listener(args[2], curpeers->peers_fe)) {
1324 err_code |= ERR_FATAL;
1325 goto out;
1326 }
1327 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1328 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1329 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1330 curpeers->peers_fe->listen->accept = session_accept;
1331 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1332 curpeers->peers_fe->listen->handler = process_session;
1333 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1334 }
1335 }
1336 } /* neither "peer" nor "peers" */
1337 else if (*args[0] != 0) {
1338 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342
1343out:
1344 return err_code;
1345}
1346
1347
Willy Tarreau3842f002009-06-14 11:39:52 +02001348int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349{
1350 static struct proxy *curproxy = NULL;
1351 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001352 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001353 int rc;
1354 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001355 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001356 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357
Willy Tarreau977b8e42006-12-29 14:19:17 +01001358 if (!strcmp(args[0], "listen"))
1359 rc = PR_CAP_LISTEN;
1360 else if (!strcmp(args[0], "frontend"))
1361 rc = PR_CAP_FE | PR_CAP_RS;
1362 else if (!strcmp(args[0], "backend"))
1363 rc = PR_CAP_BE | PR_CAP_RS;
1364 else if (!strcmp(args[0], "ruleset"))
1365 rc = PR_CAP_RS;
1366 else
1367 rc = PR_CAP_NONE;
1368
1369 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 if (!*args[1]) {
1371 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1372 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_ABORT;
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001377
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001378 err = invalid_char(args[1]);
1379 if (err) {
1380 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1381 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001383 }
1384
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001385 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1386 /*
1387 * If there are two proxies with the same name only following
1388 * combinations are allowed:
1389 *
1390 * listen backend frontend ruleset
1391 * listen - - - -
1392 * backend - - OK -
1393 * frontend - OK - -
1394 * ruleset - - - -
1395 */
1396
1397 if (!strcmp(curproxy->id, args[1]) &&
1398 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1399 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001400 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1401 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1402 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001403 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001404 }
1405 }
1406
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001409 err_code |= ERR_ALERT | ERR_ABORT;
1410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001412
Willy Tarreau97cb7802010-01-03 20:23:58 +01001413 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 curproxy->next = proxy;
1415 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001416 curproxy->conf.file = file;
1417 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001418 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421
1422 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001424 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001425 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001426 err_code |= ERR_FATAL;
1427 goto out;
1428 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001429 new = curproxy->listen;
1430 while (new != last) {
1431 new->conf.file = file;
1432 new->conf.line = linenum;
1433 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001434 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 }
1437
1438 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001439 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001440 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001441
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001444 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001445 curproxy->no_options = defproxy.no_options;
1446 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001447 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001448 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001449 curproxy->except_net = defproxy.except_net;
1450 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001451 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001452 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001454 if (defproxy.fwdfor_hdr_len) {
1455 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1456 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1457 }
1458
Willy Tarreaub86db342009-11-30 11:50:16 +01001459 if (defproxy.orgto_hdr_len) {
1460 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1461 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1462 }
1463
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (curproxy->cap & PR_CAP_FE) {
1465 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001466 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001467 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468
1469 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001470 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1471 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472
1473 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475
Willy Tarreau977b8e42006-12-29 14:19:17 +01001476 if (curproxy->cap & PR_CAP_BE) {
1477 curproxy->fullconn = defproxy.fullconn;
1478 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001480 if (defproxy.check_req) {
1481 curproxy->check_req = calloc(1, defproxy.check_len);
1482 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1483 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001484 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 if (defproxy.cookie_name)
1487 curproxy->cookie_name = strdup(defproxy.cookie_name);
1488 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001489 if (defproxy.cookie_domain)
1490 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001491
Willy Tarreau31936852010-10-06 16:59:56 +02001492 if (defproxy.cookie_maxidle)
1493 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1494
1495 if (defproxy.cookie_maxlife)
1496 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1497
Emeric Brun647caf12009-06-30 17:57:00 +02001498 if (defproxy.rdp_cookie_name)
1499 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1500 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1501
Willy Tarreau01732802007-11-01 22:48:15 +01001502 if (defproxy.url_param_name)
1503 curproxy->url_param_name = strdup(defproxy.url_param_name);
1504 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001505
Benoitaffb4812009-03-25 13:02:10 +01001506 if (defproxy.hh_name)
1507 curproxy->hh_name = strdup(defproxy.hh_name);
1508 curproxy->hh_len = defproxy.hh_len;
1509 curproxy->hh_match_domain = defproxy.hh_match_domain;
1510
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001511 if (defproxy.iface_name)
1512 curproxy->iface_name = strdup(defproxy.iface_name);
1513 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001516 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001517 if (defproxy.capture_name)
1518 curproxy->capture_name = strdup(defproxy.capture_name);
1519 curproxy->capture_namelen = defproxy.capture_namelen;
1520 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522
Willy Tarreau977b8e42006-12-29 14:19:17 +01001523 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001524 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001525 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001526 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001527 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001528 curproxy->uri_auth = defproxy.uri_auth;
1529 curproxy->mon_net = defproxy.mon_net;
1530 curproxy->mon_mask = defproxy.mon_mask;
1531 if (defproxy.monitor_uri)
1532 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1533 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001534 if (defproxy.defbe.name)
1535 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 }
1537
1538 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001539 curproxy->timeout.connect = defproxy.timeout.connect;
1540 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001541 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001542 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001543 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001544 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001545 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001546 curproxy->source_addr = defproxy.source_addr;
1547 }
1548
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 curproxy->mode = defproxy.mode;
1550 curproxy->logfac1 = defproxy.logfac1;
1551 curproxy->logsrv1 = defproxy.logsrv1;
1552 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001553 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 curproxy->logfac2 = defproxy.logfac2;
1555 curproxy->logsrv2 = defproxy.logsrv2;
1556 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001557 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001559 curproxy->conf.used_listener_id = EB_ROOT;
1560 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001561
Willy Tarreau93893792009-07-23 13:19:11 +02001562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 }
1564 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1565 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001566 /* FIXME-20070101: we should do this too at the end of the
1567 * config parsing to free all default values.
1568 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001569 free(defproxy.check_req);
1570 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001571 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001572 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001573 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001574 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001575 free(defproxy.capture_name);
1576 free(defproxy.monitor_uri);
1577 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001578 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001579 free(defproxy.fwdfor_hdr_name);
1580 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001581 free(defproxy.orgto_hdr_name);
1582 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001583
Willy Tarreaua534fea2008-08-03 12:19:50 +02001584 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001585 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001586
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 /* we cannot free uri_auth because it might already be used */
1588 init_default_instance();
1589 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 }
1593 else if (curproxy == NULL) {
1594 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 }
1598
Willy Tarreau977b8e42006-12-29 14:19:17 +01001599
1600 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001602 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001603 int cur_arg;
1604
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 if (curproxy == &defproxy) {
1606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001611 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612
Emeric Bruned760922010-10-22 17:59:25 +02001613 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001614 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001619
1620 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001621
1622 /* NOTE: the following line might create several listeners if there
1623 * are comma-separated IPs or port ranges. So all further processing
1624 * will have to be applied to all listeners created after last_listen.
1625 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001626 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
1629 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001630
Willy Tarreau90a570f2009-10-04 20:54:54 +02001631 new_listen = curproxy->listen;
1632 while (new_listen != last_listen) {
1633 new_listen->conf.file = file;
1634 new_listen->conf.line = linenum;
1635 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001636 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001637 }
1638
Emeric Bruned760922010-10-22 17:59:25 +02001639 /* Set default global rights and owner for unix bind */
1640 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1641 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1642 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001643 cur_arg = 2;
1644 while (*(args[cur_arg])) {
1645 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1646#ifdef SO_BINDTODEVICE
1647 struct listener *l;
1648
Emeric Bruned760922010-10-22 17:59:25 +02001649 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1650 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1651 file, linenum, args[0], args[cur_arg]);
1652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
1654 }
1655
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001656 if (!*args[cur_arg + 1]) {
1657 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001661 }
1662
1663 for (l = curproxy->listen; l != last_listen; l = l->next)
1664 l->interface = strdup(args[cur_arg + 1]);
1665
1666 global.last_checks |= LSTCHK_NETADM;
1667
1668 cur_arg += 2;
1669 continue;
1670#else
1671 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1672 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
1674 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001675#endif
1676 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001677 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1678#ifdef TCP_MAXSEG
1679 struct listener *l;
1680 int mss;
1681
Emeric Bruned760922010-10-22 17:59:25 +02001682 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1683 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1684 file, linenum, args[0], args[cur_arg]);
1685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
1687 }
1688
Willy Tarreaube1b9182009-06-14 18:48:19 +02001689 if (!*args[cur_arg + 1]) {
1690 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1691 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001692 err_code |= ERR_ALERT | ERR_FATAL;
1693 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001694 }
1695
Willy Tarreau48a7e722010-12-24 15:26:39 +01001696 mss = atoi(args[cur_arg + 1]);
1697 if (!mss || abs(mss) > 65535) {
1698 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001702 }
1703
1704 for (l = curproxy->listen; l != last_listen; l = l->next)
1705 l->maxseg = mss;
1706
1707 cur_arg += 2;
1708 continue;
1709#else
1710 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1711 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001714#endif
1715 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001716
1717 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1718#ifdef TCP_DEFER_ACCEPT
1719 struct listener *l;
1720
1721 for (l = curproxy->listen; l != last_listen; l = l->next)
1722 l->options |= LI_O_DEF_ACCEPT;
1723
1724 cur_arg ++;
1725 continue;
1726#else
1727 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1728 file, linenum, args[0], args[cur_arg]);
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
1731#endif
1732 }
1733
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001734 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001735#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001736 struct listener *l;
1737
Emeric Bruned760922010-10-22 17:59:25 +02001738 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1739 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1740 file, linenum, args[0], args[cur_arg]);
1741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
1743 }
1744
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001745 for (l = curproxy->listen; l != last_listen; l = l->next)
1746 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001747
1748 cur_arg ++;
1749 continue;
1750#else
1751 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1752 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001755#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001756 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001757
Willy Tarreau8a956912010-10-15 14:27:08 +02001758 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1759 struct listener *l;
1760
1761 for (l = curproxy->listen; l != last_listen; l = l->next)
1762 l->options |= LI_O_ACC_PROXY;
1763
1764 cur_arg ++;
1765 continue;
1766 }
1767
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001768 if (!strcmp(args[cur_arg], "name")) {
1769 struct listener *l;
1770
1771 for (l = curproxy->listen; l != last_listen; l = l->next)
1772 l->name = strdup(args[cur_arg + 1]);
1773
1774 cur_arg += 2;
1775 continue;
1776 }
1777
1778 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001779 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001780 struct listener *l;
1781
1782 if (curproxy->listen->next != last_listen) {
1783 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1784 file, linenum, args[cur_arg]);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788
1789 if (!*args[cur_arg + 1]) {
1790 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1791 file, linenum, args[cur_arg]);
1792 err_code |= ERR_ALERT | ERR_FATAL;
1793 goto out;
1794 }
1795
1796 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001797 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001798
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001799 if (curproxy->listen->luid <= 0) {
1800 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001801 file, linenum);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804 }
1805
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001806 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1807 if (node) {
1808 l = container_of(node, struct listener, conf.id);
1809 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1810 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
1814 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1815
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001816 cur_arg += 2;
1817 continue;
1818 }
1819
Emeric Bruned760922010-10-22 17:59:25 +02001820 if (!strcmp(args[cur_arg], "mode")) {
1821
1822 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1823 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1824 file, linenum, args[0], args[cur_arg]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
1828
1829 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1830
1831 cur_arg += 2;
1832 continue;
1833 }
1834
1835 if (!strcmp(args[cur_arg], "uid")) {
1836
1837 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1838 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1839 file, linenum, args[0], args[cur_arg]);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843
1844 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1845 cur_arg += 2;
1846 continue;
1847 }
1848
1849 if (!strcmp(args[cur_arg], "gid")) {
1850
1851 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1852 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1853 file, linenum, args[0], args[cur_arg]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
1858 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1859 cur_arg += 2;
1860 continue;
1861 }
1862
1863 if (!strcmp(args[cur_arg], "user")) {
1864 struct passwd *user;
1865
1866 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1867 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1868 file, linenum, args[0], args[cur_arg]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872 user = getpwnam(args[cur_arg + 1]);
1873 if (!user) {
1874 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1875 file, linenum, args[0], args[cur_arg + 1 ]);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879
1880 curproxy->listen->perm.ux.uid = user->pw_uid;
1881 cur_arg += 2;
1882 continue;
1883 }
1884
1885 if (!strcmp(args[cur_arg], "group")) {
1886 struct group *group;
1887
1888 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1889 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1890 file, linenum, args[0], args[cur_arg]);
1891 err_code |= ERR_ALERT | ERR_FATAL;
1892 goto out;
1893 }
1894 group = getgrnam(args[cur_arg + 1]);
1895 if (!group) {
1896 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1897 file, linenum, args[0], args[cur_arg + 1 ]);
1898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
1900 }
1901
1902 curproxy->listen->perm.ux.gid = group->gr_gid;
1903 cur_arg += 2;
1904 continue;
1905 }
1906
Willy Tarreau8a956912010-10-15 14:27:08 +02001907 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001911 }
Willy Tarreau93893792009-07-23 13:19:11 +02001912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 }
1914 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1915 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1916 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1917 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001918 err_code |= ERR_ALERT | ERR_FATAL;
1919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 /* flush useless bits */
1925 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001928 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931
Willy Tarreau1c47f852006-07-09 08:22:27 +02001932 if (!*args[1]) {
1933 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1934 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001937 }
1938
Willy Tarreaua534fea2008-08-03 12:19:50 +02001939 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001940 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001941 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001942 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001943 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1944
Willy Tarreau93893792009-07-23 13:19:11 +02001945 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1948 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1949 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1950 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1951 else {
1952 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 }
1956 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001957 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001958 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001959
1960 if (curproxy == &defproxy) {
1961 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001965 }
1966
1967 if (!*args[1]) {
1968 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001972 }
1973
1974 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001975 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001976
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001977 if (curproxy->uuid <= 0) {
1978 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001979 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001982 }
1983
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001984 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1985 if (node) {
1986 struct proxy *target = container_of(node, struct proxy, conf.id);
1987 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1988 file, linenum, proxy_type_str(curproxy), curproxy->id,
1989 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
1992 }
1993 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001994 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001995 else if (!strcmp(args[0], "description")) {
1996 int i, len=0;
1997 char *d;
1998
Cyril Bonté99ed3272010-01-24 23:29:44 +01001999 if (curproxy == &defproxy) {
2000 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2001 file, linenum, args[0]);
2002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
2004 }
2005
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002006 if (!*args[1]) {
2007 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2008 file, linenum, args[0]);
2009 return -1;
2010 }
2011
2012 for(i=1; *args[i]; i++)
2013 len += strlen(args[i])+1;
2014
2015 d = (char *)calloc(1, len);
2016 curproxy->desc = d;
2017
2018 d += sprintf(d, "%s", args[1]);
2019 for(i=2; *args[i]; i++)
2020 d += sprintf(d, " %s", args[i]);
2021
2022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2024 curproxy->state = PR_STSTOPPED;
2025 }
2026 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2027 curproxy->state = PR_STNEW;
2028 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002029 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2030 int cur_arg = 1;
2031 unsigned int set = 0;
2032
2033 while (*args[cur_arg]) {
2034 int u;
2035 if (strcmp(args[cur_arg], "all") == 0) {
2036 set = 0;
2037 break;
2038 }
2039 else if (strcmp(args[cur_arg], "odd") == 0) {
2040 set |= 0x55555555;
2041 }
2042 else if (strcmp(args[cur_arg], "even") == 0) {
2043 set |= 0xAAAAAAAA;
2044 }
2045 else {
2046 u = str2uic(args[cur_arg]);
2047 if (u < 1 || u > 32) {
2048 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002052 }
2053 if (u > global.nbproc) {
2054 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2055 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002057 }
2058 set |= 1 << (u - 1);
2059 }
2060 cur_arg++;
2061 }
2062 curproxy->bind_proc = set;
2063 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002064 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002065 if (curproxy == &defproxy) {
2066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002069 }
2070
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002071 err = invalid_char(args[1]);
2072 if (err) {
2073 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2074 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002076 }
2077
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002078 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2079 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2080 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002083 }
2084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2086 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 if (*(args[1]) == 0) {
2092 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002097
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002098 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002099 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002100 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002101 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002102 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 curproxy->cookie_name = strdup(args[1]);
2104 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002105
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 cur_arg = 2;
2107 while (*(args[cur_arg])) {
2108 if (!strcmp(args[cur_arg], "rewrite")) {
2109 curproxy->options |= PR_O_COOK_RW;
2110 }
2111 else if (!strcmp(args[cur_arg], "indirect")) {
2112 curproxy->options |= PR_O_COOK_IND;
2113 }
2114 else if (!strcmp(args[cur_arg], "insert")) {
2115 curproxy->options |= PR_O_COOK_INS;
2116 }
2117 else if (!strcmp(args[cur_arg], "nocache")) {
2118 curproxy->options |= PR_O_COOK_NOC;
2119 }
2120 else if (!strcmp(args[cur_arg], "postonly")) {
2121 curproxy->options |= PR_O_COOK_POST;
2122 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002123 else if (!strcmp(args[cur_arg], "preserve")) {
2124 curproxy->options2 |= PR_O2_COOK_PSV;
2125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 else if (!strcmp(args[cur_arg], "prefix")) {
2127 curproxy->options |= PR_O_COOK_PFX;
2128 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002129 else if (!strcmp(args[cur_arg], "domain")) {
2130 if (!*args[cur_arg + 1]) {
2131 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2132 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002135 }
2136
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002137 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002138 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002139 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2140 " dots nor does not start with a dot."
2141 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002142 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002143 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002144 }
2145
2146 err = invalid_domainchar(args[cur_arg + 1]);
2147 if (err) {
2148 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2149 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002152 }
2153
Willy Tarreau68a897b2009-12-03 23:28:34 +01002154 if (!curproxy->cookie_domain) {
2155 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2156 } else {
2157 /* one domain was already specified, add another one by
2158 * building the string which will be returned along with
2159 * the cookie.
2160 */
2161 char *new_ptr;
2162 int new_len = strlen(curproxy->cookie_domain) +
2163 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2164 new_ptr = malloc(new_len);
2165 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2166 free(curproxy->cookie_domain);
2167 curproxy->cookie_domain = new_ptr;
2168 }
Willy Tarreau31936852010-10-06 16:59:56 +02002169 cur_arg++;
2170 }
2171 else if (!strcmp(args[cur_arg], "maxidle")) {
2172 unsigned int maxidle;
2173 const char *res;
2174
2175 if (!*args[cur_arg + 1]) {
2176 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2177 file, linenum, args[cur_arg]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181
2182 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2183 if (res) {
2184 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2185 file, linenum, *res, args[cur_arg]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189 curproxy->cookie_maxidle = maxidle;
2190 cur_arg++;
2191 }
2192 else if (!strcmp(args[cur_arg], "maxlife")) {
2193 unsigned int maxlife;
2194 const char *res;
2195
2196 if (!*args[cur_arg + 1]) {
2197 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2198 file, linenum, args[cur_arg]);
2199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
2202
2203 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2204 if (res) {
2205 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2206 file, linenum, *res, args[cur_arg]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002211 cur_arg++;
2212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002214 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }
2219 cur_arg++;
2220 }
2221 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2222 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2223 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 }
2226
2227 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2228 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2229 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002232
2233 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2234 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2235 file, linenum);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002239 else if (!strcmp(args[0], "persist")) { /* persist */
2240 if (*(args[1]) == 0) {
2241 Alert("parsing [%s:%d] : missing persist method.\n",
2242 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002245 }
2246
2247 if (!strncmp(args[1], "rdp-cookie", 10)) {
2248 curproxy->options2 |= PR_O2_RDPC_PRST;
2249
Emeric Brunb982a3d2010-01-04 15:45:53 +01002250 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002251 const char *beg, *end;
2252
2253 beg = args[1] + 11;
2254 end = strchr(beg, ')');
2255
2256 if (!end || end == beg) {
2257 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002261 }
2262
2263 free(curproxy->rdp_cookie_name);
2264 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2265 curproxy->rdp_cookie_len = end-beg;
2266 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002267 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002268 free(curproxy->rdp_cookie_name);
2269 curproxy->rdp_cookie_name = strdup("msts");
2270 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2271 }
2272 else { /* syntax */
2273 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002277 }
2278 }
2279 else {
2280 Alert("parsing [%s:%d] : unknown persist method.\n",
2281 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002284 }
2285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002287 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002289 if (curproxy == &defproxy) {
2290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002299 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 }
2304 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->appsession_name = strdup(args[1]);
2307 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2308 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002309 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2310 if (err) {
2311 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2312 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002315 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002316 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002317
Willy Tarreau51041c72007-09-09 21:56:53 +02002318 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_ABORT;
2321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002323
2324 cur_arg = 6;
2325 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002326 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2327 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002328 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002329 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002330 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002331 } else if (!strcmp(args[cur_arg], "prefix")) {
2332 curproxy->options2 |= PR_O2_AS_PFX;
2333 } else if (!strcmp(args[cur_arg], "mode")) {
2334 if (!*args[cur_arg + 1]) {
2335 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2336 file, linenum, args[0], args[cur_arg]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 cur_arg++;
2342 if (!strcmp(args[cur_arg], "query-string")) {
2343 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2344 curproxy->options2 |= PR_O2_AS_M_QS;
2345 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2346 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2347 curproxy->options2 |= PR_O2_AS_M_PP;
2348 } else {
2349 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002354 cur_arg++;
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 } /* Url App Session */
2357 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002358 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002360
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002362 if (curproxy == &defproxy) {
2363 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
2366 }
2367
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 if (*(args[4]) == 0) {
2369 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002374 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 curproxy->capture_name = strdup(args[2]);
2376 curproxy->capture_namelen = strlen(curproxy->capture_name);
2377 curproxy->capture_len = atol(args[4]);
2378 if (curproxy->capture_len >= CAPTURE_LEN) {
2379 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2380 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 curproxy->capture_len = CAPTURE_LEN - 1;
2383 }
2384 curproxy->to_log |= LW_COOKIE;
2385 }
2386 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2387 struct cap_hdr *hdr;
2388
2389 if (curproxy == &defproxy) {
2390 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394
2395 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2396 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2397 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401
2402 hdr = calloc(sizeof(struct cap_hdr), 1);
2403 hdr->next = curproxy->req_cap;
2404 hdr->name = strdup(args[3]);
2405 hdr->namelen = strlen(args[3]);
2406 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002407 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 hdr->index = curproxy->nb_req_cap++;
2409 curproxy->req_cap = hdr;
2410 curproxy->to_log |= LW_REQHDR;
2411 }
2412 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2413 struct cap_hdr *hdr;
2414
2415 if (curproxy == &defproxy) {
2416 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420
2421 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2422 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2423 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427 hdr = calloc(sizeof(struct cap_hdr), 1);
2428 hdr->next = curproxy->rsp_cap;
2429 hdr->name = strdup(args[3]);
2430 hdr->namelen = strlen(args[3]);
2431 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002432 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 hdr->index = curproxy->nb_rsp_cap++;
2434 curproxy->rsp_cap = hdr;
2435 curproxy->to_log |= LW_RSPHDR;
2436 }
2437 else {
2438 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 if (*(args[1]) == 0) {
2449 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 }
2454 curproxy->conn_retries = atol(args[1]);
2455 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002456 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2457 struct req_acl_rule *req_acl;
2458
2459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
2465
2466 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2467 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2468 file, linenum, args[0]);
2469 err_code |= ERR_WARN;
2470 }
2471
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002472 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002473
2474 if (!req_acl) {
2475 err_code |= ERR_ALERT | ERR_ABORT;
2476 goto out;
2477 }
2478
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002479 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002480 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2481 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002483 if (curproxy == &defproxy) {
2484 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002487 }
2488
Willy Tarreauef6494c2010-01-28 17:12:36 +01002489 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002490 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002494 }
2495
Willy Tarreauef6494c2010-01-28 17:12:36 +01002496 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002497 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2498 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002501 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002502
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002503 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002504 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002505 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002506 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002507 struct redirect_rule *rule;
2508 int cur_arg;
2509 int type = REDIRECT_TYPE_NONE;
2510 int code = 302;
2511 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002512 char *cookie = NULL;
2513 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002514 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002515
Cyril Bonté99ed3272010-01-24 23:29:44 +01002516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 cur_arg = 1;
2523 while (*(args[cur_arg])) {
2524 if (!strcmp(args[cur_arg], "location")) {
2525 if (!*args[cur_arg + 1]) {
2526 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2527 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 }
2531
2532 type = REDIRECT_TYPE_LOCATION;
2533 cur_arg++;
2534 destination = args[cur_arg];
2535 }
2536 else if (!strcmp(args[cur_arg], "prefix")) {
2537 if (!*args[cur_arg + 1]) {
2538 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2539 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002542 }
2543
2544 type = REDIRECT_TYPE_PREFIX;
2545 cur_arg++;
2546 destination = args[cur_arg];
2547 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002548 else if (!strcmp(args[cur_arg], "set-cookie")) {
2549 if (!*args[cur_arg + 1]) {
2550 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2551 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002554 }
2555
2556 cur_arg++;
2557 cookie = args[cur_arg];
2558 cookie_set = 1;
2559 }
2560 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2561 if (!*args[cur_arg + 1]) {
2562 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2563 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002566 }
2567
2568 cur_arg++;
2569 cookie = args[cur_arg];
2570 cookie_set = 0;
2571 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002572 else if (!strcmp(args[cur_arg],"code")) {
2573 if (!*args[cur_arg + 1]) {
2574 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002578 }
2579 cur_arg++;
2580 code = atol(args[cur_arg]);
2581 if (code < 301 || code > 303) {
2582 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2583 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 }
2587 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002588 else if (!strcmp(args[cur_arg],"drop-query")) {
2589 flags |= REDIRECT_FLAG_DROP_QS;
2590 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002591 else if (!strcmp(args[cur_arg],"append-slash")) {
2592 flags |= REDIRECT_FLAG_APPEND_SLASH;
2593 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002594 else if (strcmp(args[cur_arg], "if") == 0 ||
2595 strcmp(args[cur_arg], "unless") == 0) {
2596 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2597 if (!cond) {
2598 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2599 file, linenum, args[0]);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002603 break;
2604 }
2605 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002606 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002607 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002610 }
2611 cur_arg++;
2612 }
2613
2614 if (type == REDIRECT_TYPE_NONE) {
2615 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002619 }
2620
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002621 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2622 rule->cond = cond;
2623 rule->rdr_str = strdup(destination);
2624 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002625 if (cookie) {
2626 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002627 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002628 */
2629 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002630 if (cookie_set) {
2631 rule->cookie_str = malloc(rule->cookie_len + 10);
2632 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2633 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2634 rule->cookie_len += 9;
2635 } else {
2636 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002637 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002638 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2639 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002640 }
2641 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002642 rule->type = type;
2643 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002644 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002645 LIST_INIT(&rule->list);
2646 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002647 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2648 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002650 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002651 struct switching_rule *rule;
2652
Willy Tarreaub099aca2008-10-12 17:26:37 +02002653 if (curproxy == &defproxy) {
2654 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002657 }
2658
Willy Tarreau55ea7572007-06-17 19:56:27 +02002659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002660 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002661
2662 if (*(args[1]) == 0) {
2663 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002666 }
2667
Willy Tarreauef6494c2010-01-28 17:12:36 +01002668 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002669 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2670 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002673 }
2674
Willy Tarreauef6494c2010-01-28 17:12:36 +01002675 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002676 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002677 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680 }
2681
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002682 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002683
Willy Tarreau55ea7572007-06-17 19:56:27 +02002684 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2685 rule->cond = cond;
2686 rule->be.name = strdup(args[1]);
2687 LIST_INIT(&rule->list);
2688 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2689 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002690 else if ((!strcmp(args[0], "force-persist")) ||
2691 (!strcmp(args[0], "ignore-persist"))) {
2692 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002693
2694 if (curproxy == &defproxy) {
2695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699
2700 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2701 err_code |= ERR_WARN;
2702
Willy Tarreauef6494c2010-01-28 17:12:36 +01002703 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002704 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2705 file, linenum, args[0]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
2709
Willy Tarreauef6494c2010-01-28 17:12:36 +01002710 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002711 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2712 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002717 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002718
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002719 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002720 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002721 if (!strcmp(args[0], "force-persist")) {
2722 rule->type = PERSIST_TYPE_FORCE;
2723 } else {
2724 rule->type = PERSIST_TYPE_IGNORE;
2725 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002726 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002727 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002728 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 else if (!strcmp(args[0], "stick-table")) {
2730 int myidx = 1;
2731
Emeric Brun32da3c42010-09-23 18:39:19 +02002732 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002733 curproxy->table.type = (unsigned int)-1;
2734 while (*args[myidx]) {
2735 const char *err;
2736
2737 if (strcmp(args[myidx], "size") == 0) {
2738 myidx++;
2739 if (!*(args[myidx])) {
2740 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2741 file, linenum, args[myidx-1]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
2745 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2746 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2747 file, linenum, *err, args[myidx-1]);
2748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002751 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002752 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002753 else if (strcmp(args[myidx], "peers") == 0) {
2754 myidx++;
2755 if (!*(args[myidx])) {
2756 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2757 file, linenum, args[myidx-1]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761 curproxy->table.peers.name = strdup(args[myidx++]);
2762 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002763 else if (strcmp(args[myidx], "expire") == 0) {
2764 myidx++;
2765 if (!*(args[myidx])) {
2766 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2767 file, linenum, args[myidx-1]);
2768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
2771 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2772 if (err) {
2773 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2774 file, linenum, *err, args[myidx-1]);
2775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002779 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002780 }
2781 else if (strcmp(args[myidx], "nopurge") == 0) {
2782 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002783 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002784 }
2785 else if (strcmp(args[myidx], "type") == 0) {
2786 myidx++;
2787 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2788 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2789 file, linenum, args[myidx]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002793 /* myidx already points to next arg */
2794 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002795 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002796 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002797 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002798
2799 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002800 nw = args[myidx];
2801 while (*nw) {
2802 /* the "store" keyword supports a comma-separated list */
2803 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002804 sa = NULL; /* store arg */
2805 while (*nw && *nw != ',') {
2806 if (*nw == '(') {
2807 *nw = 0;
2808 sa = ++nw;
2809 while (*nw != ')') {
2810 if (!*nw) {
2811 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2812 file, linenum, args[0], cw);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816 nw++;
2817 }
2818 *nw = '\0';
2819 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002820 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002821 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002822 if (*nw)
2823 *nw++ = '\0';
2824 type = stktable_get_data_type(cw);
2825 if (type < 0) {
2826 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2827 file, linenum, args[0], cw);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
Willy Tarreauac782882010-06-20 10:41:54 +02002831
2832 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2833 switch (err) {
2834 case PE_NONE: break;
2835 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002836 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2837 file, linenum, args[0], cw);
2838 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002839 break;
2840
2841 case PE_ARG_MISSING:
2842 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2843 file, linenum, args[0], cw);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846
2847 case PE_ARG_NOT_USED:
2848 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2849 file, linenum, args[0], cw);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852
2853 default:
2854 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2855 file, linenum, args[0], cw);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002858 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002859 }
2860 myidx++;
2861 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002862 else {
2863 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2864 file, linenum, args[myidx]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002868 }
2869
2870 if (!curproxy->table.size) {
2871 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2872 file, linenum);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 if (curproxy->table.type == (unsigned int)-1) {
2878 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2879 file, linenum);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883 }
2884 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002885 struct sticking_rule *rule;
2886 struct pattern_expr *expr;
2887 int myidx = 0;
2888 const char *name = NULL;
2889 int flags;
2890
2891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2898 err_code |= ERR_WARN;
2899 goto out;
2900 }
2901
2902 myidx++;
2903 if ((strcmp(args[myidx], "store") == 0) ||
2904 (strcmp(args[myidx], "store-request") == 0)) {
2905 myidx++;
2906 flags = STK_IS_STORE;
2907 }
2908 else if (strcmp(args[myidx], "store-response") == 0) {
2909 myidx++;
2910 flags = STK_IS_STORE | STK_ON_RSP;
2911 }
2912 else if (strcmp(args[myidx], "match") == 0) {
2913 myidx++;
2914 flags = STK_IS_MATCH;
2915 }
2916 else if (strcmp(args[myidx], "on") == 0) {
2917 myidx++;
2918 flags = STK_IS_MATCH | STK_IS_STORE;
2919 }
2920 else {
2921 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
2926 if (*(args[myidx]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
2931
Emeric Brun485479d2010-09-23 18:02:19 +02002932 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002933 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002934 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (flags & STK_ON_RSP) {
2940 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2941 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2942 file, linenum, args[0], expr->fetch->kw);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946 } else {
2947 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2948 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2949 file, linenum, args[0], expr->fetch->kw);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 }
2954
2955 if (strcmp(args[myidx], "table") == 0) {
2956 myidx++;
2957 name = args[myidx++];
2958 }
2959
Willy Tarreauef6494c2010-01-28 17:12:36 +01002960 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2961 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002962 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2963 file, linenum, args[0]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002967 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002968 else if (*(args[myidx])) {
2969 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2970 file, linenum, args[0], args[myidx]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
Emeric Brun97679e72010-09-23 17:56:44 +02002974 if (flags & STK_ON_RSP)
2975 err_code |= warnif_cond_requires_req(cond, file, linenum);
2976 else
2977 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002978
Emeric Brunb982a3d2010-01-04 15:45:53 +01002979 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2980 rule->cond = cond;
2981 rule->expr = expr;
2982 rule->flags = flags;
2983 rule->table.name = name ? strdup(name) : NULL;
2984 LIST_INIT(&rule->list);
2985 if (flags & STK_ON_RSP)
2986 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2987 else
2988 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002990 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002991 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002993
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2995 curproxy->uri_auth = NULL; /* we must detach from the default config */
2996
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002997 if (!*args[1]) {
2998 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002999 } else if (!strcmp(args[1], "admin")) {
3000 struct stats_admin_rule *rule;
3001
3002 if (curproxy == &defproxy) {
3003 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3009 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3010 err_code |= ERR_ALERT | ERR_ABORT;
3011 goto out;
3012 }
3013
3014 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3015 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3016 file, linenum, args[0], args[1]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3021 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3022 file, linenum, args[0], args[1]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
3026
3027 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3028
3029 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3030 rule->cond = cond;
3031 LIST_INIT(&rule->list);
3032 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 } else if (!strcmp(args[1], "uri")) {
3034 if (*(args[2]) == 0) {
3035 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3039 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_ABORT;
3041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 }
3043 } else if (!strcmp(args[1], "realm")) {
3044 if (*(args[2]) == 0) {
3045 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3049 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_ABORT;
3051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003053 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003054 unsigned interval;
3055
3056 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3057 if (err) {
3058 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3059 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003062 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3063 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_ABORT;
3065 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003066 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003067 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3068 struct req_acl_rule *req_acl;
3069
3070 if (curproxy == &defproxy) {
3071 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075
3076 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3077 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3078 err_code |= ERR_ALERT | ERR_ABORT;
3079 goto out;
3080 }
3081
3082 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3083 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3084 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3085 file, linenum, args[0]);
3086 err_code |= ERR_WARN;
3087 }
3088
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003089 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003090
3091 if (!req_acl) {
3092 err_code |= ERR_ALERT | ERR_ABORT;
3093 goto out;
3094 }
3095
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003096 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003097 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3098
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 } else if (!strcmp(args[1], "auth")) {
3100 if (*(args[2]) == 0) {
3101 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3105 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_ABORT;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 }
3109 } else if (!strcmp(args[1], "scope")) {
3110 if (*(args[2]) == 0) {
3111 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3115 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_ABORT;
3117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 }
3119 } else if (!strcmp(args[1], "enable")) {
3120 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3121 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_ABORT;
3123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003125 } else if (!strcmp(args[1], "hide-version")) {
3126 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3127 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_ABORT;
3129 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003130 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003131 } else if (!strcmp(args[1], "show-legends")) {
3132 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3133 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3134 err_code |= ERR_ALERT | ERR_ABORT;
3135 goto out;
3136 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003137 } else if (!strcmp(args[1], "show-node")) {
3138
3139 if (*args[2]) {
3140 int i;
3141 char c;
3142
3143 for (i=0; args[2][i]; i++) {
3144 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003145 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3146 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003147 break;
3148 }
3149
3150 if (!i || args[2][i]) {
3151 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3152 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3153 file, linenum, args[0], args[1]);
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157 }
3158
3159 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3160 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3161 err_code |= ERR_ALERT | ERR_ABORT;
3162 goto out;
3163 }
3164 } else if (!strcmp(args[1], "show-desc")) {
3165 char *desc = NULL;
3166
3167 if (*args[2]) {
3168 int i, len=0;
3169 char *d;
3170
3171 for(i=2; *args[i]; i++)
3172 len += strlen(args[i])+1;
3173
3174 desc = d = (char *)calloc(1, len);
3175
3176 d += sprintf(d, "%s", args[2]);
3177 for(i=3; *args[i]; i++)
3178 d += sprintf(d, " %s", args[i]);
3179 }
3180
3181 if (!*args[2] && !global.desc)
3182 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3183 file, linenum, args[1]);
3184 else {
3185 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3186 free(desc);
3187 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3188 err_code |= ERR_ALERT | ERR_ABORT;
3189 goto out;
3190 }
3191 free(desc);
3192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003194stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003195 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003196 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200 }
3201 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003202 int optnum;
3203
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003204 if (*(args[1]) == '\0') {
3205 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003210
3211 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3212 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003213 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3214 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3215 file, linenum, cfg_opts[optnum].name);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
Willy Tarreau93893792009-07-23 13:19:11 +02003219 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3220 err_code |= ERR_WARN;
3221 goto out;
3222 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003223
Willy Tarreau3842f002009-06-14 11:39:52 +02003224 curproxy->no_options &= ~cfg_opts[optnum].val;
3225 curproxy->options &= ~cfg_opts[optnum].val;
3226
3227 switch (kwm) {
3228 case KWM_STD:
3229 curproxy->options |= cfg_opts[optnum].val;
3230 break;
3231 case KWM_NO:
3232 curproxy->no_options |= cfg_opts[optnum].val;
3233 break;
3234 case KWM_DEF: /* already cleared */
3235 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003236 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003237
Willy Tarreau93893792009-07-23 13:19:11 +02003238 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003239 }
3240 }
3241
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003242 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3243 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003244 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3245 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3246 file, linenum, cfg_opts2[optnum].name);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
Willy Tarreau93893792009-07-23 13:19:11 +02003250 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3251 err_code |= ERR_WARN;
3252 goto out;
3253 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003254
Willy Tarreau3842f002009-06-14 11:39:52 +02003255 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3256 curproxy->options2 &= ~cfg_opts2[optnum].val;
3257
3258 switch (kwm) {
3259 case KWM_STD:
3260 curproxy->options2 |= cfg_opts2[optnum].val;
3261 break;
3262 case KWM_NO:
3263 curproxy->no_options2 |= cfg_opts2[optnum].val;
3264 break;
3265 case KWM_DEF: /* already cleared */
3266 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003267 }
Willy Tarreau93893792009-07-23 13:19:11 +02003268 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003269 }
3270 }
3271
Willy Tarreau3842f002009-06-14 11:39:52 +02003272 if (kwm != KWM_STD) {
3273 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003274 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003277 }
3278
Emeric Brun3a058f32009-06-30 18:26:00 +02003279 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003281 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003283 if (*(args[2]) != '\0') {
3284 if (!strcmp(args[2], "clf")) {
3285 curproxy->options2 |= PR_O2_CLFLOG;
3286 } else {
3287 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003290 }
3291 }
3292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 else if (!strcmp(args[1], "tcplog"))
3294 /* generate a detailed TCP log */
3295 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 else if (!strcmp(args[1], "tcpka")) {
3297 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003298 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003300
3301 if (curproxy->cap & PR_CAP_FE)
3302 curproxy->options |= PR_O_TCP_CLI_KA;
3303 if (curproxy->cap & PR_CAP_BE)
3304 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
3306 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_WARN;
3309
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003311 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003312 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003313 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003314 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003315 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003316 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003317 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003318 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 if (!*args[2]) { /* no argument */
3320 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3321 curproxy->check_len = strlen(DEF_CHECK_REQ);
3322 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003323 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 curproxy->check_req = (char *)malloc(reqlen);
3325 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003326 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003328 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 if (*args[4])
3330 reqlen += strlen(args[4]);
3331 else
3332 reqlen += strlen("HTTP/1.0");
3333
3334 curproxy->check_req = (char *)malloc(reqlen);
3335 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003336 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003338 }
3339 else if (!strcmp(args[1], "ssl-hello-chk")) {
3340 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003341 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003343
Willy Tarreaua534fea2008-08-03 12:19:50 +02003344 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003345 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003346 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003347 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003348 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003349 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003350 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003351 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
Willy Tarreau23677902007-05-08 23:50:35 +02003353 else if (!strcmp(args[1], "smtpchk")) {
3354 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003355 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003356 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003357 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003358 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003359 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003360 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003361 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003362 curproxy->options |= PR_O_SMTP_CHK;
3363
3364 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3365 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3366 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3367 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3368 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3369 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3370 curproxy->check_req = (char *)malloc(reqlen);
3371 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3372 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3373 } else {
3374 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3375 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3376 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3377 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3378 }
3379 }
3380 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003381 else if (!strcmp(args[1], "pgsql-check")) {
3382 /* use PostgreSQL request to check servers' health */
3383 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3384 err_code |= ERR_WARN;
3385
3386 free(curproxy->check_req);
3387 curproxy->check_req = NULL;
3388 curproxy->options &= ~PR_O_HTTP_CHK;
3389 curproxy->options &= ~PR_O_SMTP_CHK;
3390 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3391 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3392 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3393 curproxy->options2 |= PR_O2_PGSQL_CHK;
3394
3395 if (*(args[2])) {
3396 int cur_arg = 2;
3397
3398 while (*(args[cur_arg])) {
3399 if (strcmp(args[cur_arg], "user") == 0) {
3400 char * packet;
3401 uint32_t packet_len;
3402 uint32_t pv;
3403
3404 /* suboption header - needs additional argument for it */
3405 if (*(args[cur_arg+1]) == 0) {
3406 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3407 file, linenum, args[0], args[1], args[cur_arg]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
3411
3412 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3413 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3414 pv = htonl(0x30000); /* protocol version 3.0 */
3415
3416 packet = (char*) calloc(1, packet_len);
3417
3418 memcpy(packet + 4, &pv, 4);
3419
3420 /* copy "user" */
3421 memcpy(packet + 8, "user", 4);
3422
3423 /* copy username */
3424 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3425
3426 free(curproxy->check_req);
3427 curproxy->check_req = packet;
3428 curproxy->check_len = packet_len;
3429
3430 packet_len = htonl(packet_len);
3431 memcpy(packet, &packet_len, 4);
3432 cur_arg += 2;
3433 } else {
3434 /* unknown suboption - catchall */
3435 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3436 file, linenum, args[0], args[1]);
3437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
3439 }
3440 } /* end while loop */
3441 }
3442 }
3443
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003444 else if (!strcmp(args[1], "mysql-check")) {
3445 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003446 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3447 err_code |= ERR_WARN;
3448
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003449 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003450 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003451 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003452 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003453 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003454 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003455 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003456 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003457
3458 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3459 * const char mysql40_client_auth_pkt[] = {
3460 * "\x0e\x00\x00" // packet length
3461 * "\x01" // packet number
3462 * "\x00\x00" // client capabilities
3463 * "\x00\x00\x01" // max packet
3464 * "haproxy\x00" // username (null terminated string)
3465 * "\x00" // filler (always 0x00)
3466 * "\x01\x00\x00" // packet length
3467 * "\x00" // packet number
3468 * "\x01" // COM_QUIT command
3469 * };
3470 */
3471
3472 if (*(args[2])) {
3473 int cur_arg = 2;
3474
3475 while (*(args[cur_arg])) {
3476 if (strcmp(args[cur_arg], "user") == 0) {
3477 char *mysqluser;
3478 int packetlen, reqlen, userlen;
3479
3480 /* suboption header - needs additional argument for it */
3481 if (*(args[cur_arg+1]) == 0) {
3482 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3483 file, linenum, args[0], args[1], args[cur_arg]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
3487 mysqluser = args[cur_arg + 1];
3488 userlen = strlen(mysqluser);
3489 packetlen = userlen + 7;
3490 reqlen = packetlen + 9;
3491
3492 free(curproxy->check_req);
3493 curproxy->check_req = (char *)calloc(1, reqlen);
3494 curproxy->check_len = reqlen;
3495
3496 snprintf(curproxy->check_req, 4, "%c%c%c",
3497 ((unsigned char) packetlen & 0xff),
3498 ((unsigned char) (packetlen >> 8) & 0xff),
3499 ((unsigned char) (packetlen >> 16) & 0xff));
3500
3501 curproxy->check_req[3] = 1;
3502 curproxy->check_req[8] = 1;
3503 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3504 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3505 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3506 cur_arg += 2;
3507 } else {
3508 /* unknown suboption - catchall */
3509 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3510 file, linenum, args[0], args[1]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514 } /* end while loop */
3515 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003516 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003517 else if (!strcmp(args[1], "ldap-check")) {
3518 /* use LDAP request to check servers' health */
3519 free(curproxy->check_req);
3520 curproxy->check_req = NULL;
3521 curproxy->options &= ~PR_O_HTTP_CHK;
3522 curproxy->options &= ~PR_O_SMTP_CHK;
3523 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3524 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003525 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003526 curproxy->options2 |= PR_O2_LDAP_CHK;
3527
3528 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3529 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3530 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3531 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003532 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003533 int cur_arg;
3534
3535 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3536 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003537 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003538
3539 curproxy->options |= PR_O_FWDFOR;
3540
3541 free(curproxy->fwdfor_hdr_name);
3542 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3543 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3544
3545 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3546 cur_arg = 2;
3547 while (*(args[cur_arg])) {
3548 if (!strcmp(args[cur_arg], "except")) {
3549 /* suboption except - needs additional argument for it */
3550 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3551 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3552 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003555 }
3556 /* flush useless bits */
3557 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003558 cur_arg += 2;
3559 } else if (!strcmp(args[cur_arg], "header")) {
3560 /* suboption header - needs additional argument for it */
3561 if (*(args[cur_arg+1]) == 0) {
3562 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3563 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003566 }
3567 free(curproxy->fwdfor_hdr_name);
3568 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3569 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3570 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003571 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003572 /* unknown suboption - catchall */
3573 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3574 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003577 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003578 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003579 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003580 else if (!strcmp(args[1], "originalto")) {
3581 int cur_arg;
3582
3583 /* insert x-original-to field, but not for the IP address listed as an except.
3584 * set default options (ie: bitfield, header name, etc)
3585 */
3586
3587 curproxy->options |= PR_O_ORGTO;
3588
3589 free(curproxy->orgto_hdr_name);
3590 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3591 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3592
3593 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3594 cur_arg = 2;
3595 while (*(args[cur_arg])) {
3596 if (!strcmp(args[cur_arg], "except")) {
3597 /* suboption except - needs additional argument for it */
3598 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3599 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3600 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003603 }
3604 /* flush useless bits */
3605 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3606 cur_arg += 2;
3607 } else if (!strcmp(args[cur_arg], "header")) {
3608 /* suboption header - needs additional argument for it */
3609 if (*(args[cur_arg+1]) == 0) {
3610 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3611 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003614 }
3615 free(curproxy->orgto_hdr_name);
3616 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3617 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3618 cur_arg += 2;
3619 } else {
3620 /* unknown suboption - catchall */
3621 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3622 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003625 }
3626 } /* end while loop */
3627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 else {
3629 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
Willy Tarreau93893792009-07-23 13:19:11 +02003633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003635 else if (!strcmp(args[0], "default_backend")) {
3636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003638
3639 if (*(args[1]) == 0) {
3640 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003643 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003644 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003645 curproxy->defbe.name = strdup(args[1]);
3646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003650
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003651 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 /* enable reconnections to dispatch */
3655 curproxy->options |= PR_O_REDISP;
3656 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003657 else if (!strcmp(args[0], "http-check")) {
3658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003660
3661 if (strcmp(args[1], "disable-on-404") == 0) {
3662 /* enable a graceful server shutdown on an HTTP 404 response */
3663 curproxy->options |= PR_O_DISABLE404;
3664 }
Willy Tarreauef781042010-01-27 11:53:01 +01003665 else if (strcmp(args[1], "send-state") == 0) {
3666 /* enable emission of the apparent state of a server in HTTP checks */
3667 curproxy->options2 |= PR_O2_CHK_SNDST;
3668 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003669 else if (strcmp(args[1], "expect") == 0) {
3670 const char *ptr_arg;
3671 int cur_arg;
3672
3673 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3674 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
3677 }
3678
3679 cur_arg = 2;
3680 /* consider exclamation marks, sole or at the beginning of a word */
3681 while (*(ptr_arg = args[cur_arg])) {
3682 while (*ptr_arg == '!') {
3683 curproxy->options2 ^= PR_O2_EXP_INV;
3684 ptr_arg++;
3685 }
3686 if (*ptr_arg)
3687 break;
3688 cur_arg++;
3689 }
3690 /* now ptr_arg points to the beginning of a word past any possible
3691 * exclamation mark, and cur_arg is the argument which holds this word.
3692 */
3693 if (strcmp(ptr_arg, "status") == 0) {
3694 if (!*(args[cur_arg + 1])) {
3695 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3696 file, linenum, args[0], args[1], ptr_arg);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700 curproxy->options2 |= PR_O2_EXP_STS;
3701 curproxy->expect_str = strdup(args[cur_arg + 1]);
3702 }
3703 else if (strcmp(ptr_arg, "string") == 0) {
3704 if (!*(args[cur_arg + 1])) {
3705 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3706 file, linenum, args[0], args[1], ptr_arg);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710 curproxy->options2 |= PR_O2_EXP_STR;
3711 curproxy->expect_str = strdup(args[cur_arg + 1]);
3712 }
3713 else if (strcmp(ptr_arg, "rstatus") == 0) {
3714 if (!*(args[cur_arg + 1])) {
3715 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3716 file, linenum, args[0], args[1], ptr_arg);
3717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
3719 }
3720 curproxy->options2 |= PR_O2_EXP_RSTS;
3721 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3722 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3723 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3724 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
3728 }
3729 else if (strcmp(ptr_arg, "rstring") == 0) {
3730 if (!*(args[cur_arg + 1])) {
3731 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3732 file, linenum, args[0], args[1], ptr_arg);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736 curproxy->options2 |= PR_O2_EXP_RSTR;
3737 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3738 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3739 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3740 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
3743 }
3744 }
3745 else {
3746 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3747 file, linenum, args[0], args[1], ptr_arg);
3748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
3750 }
3751 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003752 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003753 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003756 }
3757 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003758 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003759 if (curproxy == &defproxy) {
3760 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003763 }
3764
Willy Tarreaub80c2302007-11-30 20:51:32 +01003765 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003767
3768 if (strcmp(args[1], "fail") == 0) {
3769 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003770 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003771 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3772 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003775 }
3776
Willy Tarreauef6494c2010-01-28 17:12:36 +01003777 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003778 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3779 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003782 }
3783 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3784 }
3785 else {
3786 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003789 }
3790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791#ifdef TPROXY
3792 else if (!strcmp(args[0], "transparent")) {
3793 /* enable transparent proxy connections */
3794 curproxy->options |= PR_O_TRANSP;
3795 }
3796#endif
3797 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003800
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 if (*(args[1]) == 0) {
3802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
3806 curproxy->maxconn = atol(args[1]);
3807 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003808 else if (!strcmp(args[0], "backlog")) { /* backlog */
3809 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003811
3812 if (*(args[1]) == 0) {
3813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003816 }
3817 curproxy->backlog = atol(args[1]);
3818 }
Willy Tarreau86034312006-12-29 00:10:33 +01003819 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003822
Willy Tarreau86034312006-12-29 00:10:33 +01003823 if (*(args[1]) == 0) {
3824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003827 }
3828 curproxy->fullconn = atol(args[1]);
3829 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3831 if (*(args[1]) == 0) {
3832 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003836 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3837 if (err) {
3838 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3839 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003842 }
3843 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
3845 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003846 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 if (curproxy == &defproxy) {
3848 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003852 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003854
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 if (strchr(args[1], ':') == NULL) {
3856 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003860 sk = str2sa(args[1]);
3861 if (!sk) {
3862 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
3868 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003869 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003871
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003872 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003873 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3874 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003879 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3880 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3881 err_code |= ERR_WARN;
3882
3883 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3884 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3885 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3886 }
3887 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3888 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3889 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3890 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003891 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3892 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3893 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3894 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003895 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003896 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
3899 }
3900 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003901 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003903 char *rport, *raddr;
3904 short realport = 0;
3905 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003907 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003908 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003912 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914
3915 if (!*args[2]) {
3916 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3917 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003920 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003921
3922 err = invalid_char(args[1]);
3923 if (err) {
3924 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3925 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003928 }
3929
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003930 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003931 struct sockaddr_in *sk;
3932
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003933 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3934 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3935 err_code |= ERR_ALERT | ERR_ABORT;
3936 goto out;
3937 }
3938
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003939 /* the servers are linked backwards first */
3940 newsrv->next = curproxy->srv;
3941 curproxy->srv = newsrv;
3942 newsrv->proxy = curproxy;
3943 newsrv->conf.file = file;
3944 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003946 LIST_INIT(&newsrv->pendconns);
3947 do_check = 0;
3948 newsrv->state = SRV_RUNNING; /* early server setup */
3949 newsrv->last_change = now.tv_sec;
3950 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003952 /* several ways to check the port component :
3953 * - IP => port=+0, relative
3954 * - IP: => port=+0, relative
3955 * - IP:N => port=N, absolute
3956 * - IP:+N => port=+N, relative
3957 * - IP:-N => port=-N, relative
3958 */
3959 raddr = strdup(args[2]);
3960 rport = strchr(raddr, ':');
3961 if (rport) {
3962 *rport++ = 0;
3963 realport = atol(rport);
3964 if (!isdigit((unsigned char)*rport))
3965 newsrv->state |= SRV_MAPPORTS;
3966 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003968
Willy Tarreaud5191e72010-02-09 20:50:45 +01003969 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003970 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003971 if (!sk) {
3972 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
3976 newsrv->addr = *sk;
3977 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003978
3979 newsrv->check_port = curproxy->defsrv.check_port;
3980 newsrv->inter = curproxy->defsrv.inter;
3981 newsrv->fastinter = curproxy->defsrv.fastinter;
3982 newsrv->downinter = curproxy->defsrv.downinter;
3983 newsrv->rise = curproxy->defsrv.rise;
3984 newsrv->fall = curproxy->defsrv.fall;
3985 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3986 newsrv->minconn = curproxy->defsrv.minconn;
3987 newsrv->maxconn = curproxy->defsrv.maxconn;
3988 newsrv->slowstart = curproxy->defsrv.slowstart;
3989 newsrv->onerror = curproxy->defsrv.onerror;
3990 newsrv->consecutive_errors_limit
3991 = curproxy->defsrv.consecutive_errors_limit;
3992 newsrv->uweight = newsrv->iweight
3993 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003995 newsrv->curfd = -1; /* no health-check in progress */
3996 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003998 cur_arg = 3;
3999 } else {
4000 newsrv = &curproxy->defsrv;
4001 cur_arg = 1;
4002 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004003
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004005 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004006 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004007
4008 if (!*args[cur_arg + 1]) {
4009 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4010 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004013 }
4014
4015 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004016 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004017
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004018 if (newsrv->puid <= 0) {
4019 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004020 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004023 }
4024
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004025 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4026 if (node) {
4027 struct server *target = container_of(node, struct server, conf.id);
4028 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4029 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
4033 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004034 cur_arg += 2;
4035 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004036 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 newsrv->cookie = strdup(args[cur_arg + 1]);
4038 newsrv->cklen = strlen(args[cur_arg + 1]);
4039 cur_arg += 2;
4040 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004041 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004042 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4043 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4044 cur_arg += 2;
4045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004047 if (!*args[cur_arg + 1]) {
4048 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4049 file, linenum, args[cur_arg]);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004055 if (newsrv->rise <= 0) {
4056 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4057 file, linenum, args[cur_arg]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061
Willy Tarreau96839092010-03-29 10:02:24 +02004062 if (newsrv->health)
4063 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 cur_arg += 2;
4065 }
4066 else if (!strcmp(args[cur_arg], "fall")) {
4067 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004068
4069 if (!*args[cur_arg + 1]) {
4070 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4071 file, linenum, args[cur_arg]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075
4076 if (newsrv->fall <= 0) {
4077 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4078 file, linenum, args[cur_arg]);
4079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
4081 }
4082
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083 cur_arg += 2;
4084 }
4085 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004086 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4087 if (err) {
4088 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4089 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004092 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004093 if (val <= 0) {
4094 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4095 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004098 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004099 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 cur_arg += 2;
4101 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 else if (!strcmp(args[cur_arg], "fastinter")) {
4103 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4104 if (err) {
4105 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4106 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004109 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004110 if (val <= 0) {
4111 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4112 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004115 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004116 newsrv->fastinter = val;
4117 cur_arg += 2;
4118 }
4119 else if (!strcmp(args[cur_arg], "downinter")) {
4120 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4121 if (err) {
4122 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4123 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004126 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004127 if (val <= 0) {
4128 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4129 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004132 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004133 newsrv->downinter = val;
4134 cur_arg += 2;
4135 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004136 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004137 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4138 if (!sk) {
4139 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004144 cur_arg += 2;
4145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 else if (!strcmp(args[cur_arg], "port")) {
4147 newsrv->check_port = atol(args[cur_arg + 1]);
4148 cur_arg += 2;
4149 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004150 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 newsrv->state |= SRV_BACKUP;
4152 cur_arg ++;
4153 }
4154 else if (!strcmp(args[cur_arg], "weight")) {
4155 int w;
4156 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004157 if (w < 0 || w > 256) {
4158 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004163 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 cur_arg += 2;
4165 }
4166 else if (!strcmp(args[cur_arg], "minconn")) {
4167 newsrv->minconn = atol(args[cur_arg + 1]);
4168 cur_arg += 2;
4169 }
4170 else if (!strcmp(args[cur_arg], "maxconn")) {
4171 newsrv->maxconn = atol(args[cur_arg + 1]);
4172 cur_arg += 2;
4173 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004174 else if (!strcmp(args[cur_arg], "maxqueue")) {
4175 newsrv->maxqueue = atol(args[cur_arg + 1]);
4176 cur_arg += 2;
4177 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004178 else if (!strcmp(args[cur_arg], "slowstart")) {
4179 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004180 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004181 if (err) {
4182 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4183 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004186 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004187 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004188 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4189 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004192 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004193 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004194 cur_arg += 2;
4195 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004196 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004197
4198 if (!*args[cur_arg + 1]) {
4199 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4200 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004203 }
4204
4205 newsrv->trackit = strdup(args[cur_arg + 1]);
4206
4207 cur_arg += 2;
4208 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004209 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 global.maxsock++;
4211 do_check = 1;
4212 cur_arg += 1;
4213 }
Willy Tarreau96839092010-03-29 10:02:24 +02004214 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4215 newsrv->state |= SRV_MAINTAIN;
4216 newsrv->state &= ~SRV_RUNNING;
4217 newsrv->health = 0;
4218 cur_arg += 1;
4219 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004220 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004221 if (!strcmp(args[cur_arg + 1], "none"))
4222 newsrv->observe = HANA_OBS_NONE;
4223 else if (!strcmp(args[cur_arg + 1], "layer4"))
4224 newsrv->observe = HANA_OBS_LAYER4;
4225 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4226 if (curproxy->mode != PR_MODE_HTTP) {
4227 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4228 file, linenum, args[cur_arg + 1]);
4229 err_code |= ERR_ALERT;
4230 }
4231 newsrv->observe = HANA_OBS_LAYER7;
4232 }
4233 else {
4234 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004235 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004236 file, linenum, args[cur_arg], args[cur_arg + 1]);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
4239 }
4240
4241 cur_arg += 2;
4242 }
4243 else if (!strcmp(args[cur_arg], "on-error")) {
4244 if (!strcmp(args[cur_arg + 1], "fastinter"))
4245 newsrv->onerror = HANA_ONERR_FASTINTER;
4246 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4247 newsrv->onerror = HANA_ONERR_FAILCHK;
4248 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4249 newsrv->onerror = HANA_ONERR_SUDDTH;
4250 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4251 newsrv->onerror = HANA_ONERR_MARKDWN;
4252 else {
4253 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004254 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004255 file, linenum, args[cur_arg], args[cur_arg + 1]);
4256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
4258 }
4259
4260 cur_arg += 2;
4261 }
4262 else if (!strcmp(args[cur_arg], "error-limit")) {
4263 if (!*args[cur_arg + 1]) {
4264 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4265 file, linenum, args[cur_arg]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269
4270 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4271
4272 if (newsrv->consecutive_errors_limit <= 0) {
4273 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4274 file, linenum, args[cur_arg]);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004278 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004279 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004280 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004281 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004282 struct sockaddr_in *sk;
4283
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004285#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004286 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004287 file, linenum, "source", "usesrc");
4288#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004289 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004291#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 }
4295 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004296 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4297 if (!sk) {
4298 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004303
4304 if (port_low != port_high) {
4305 int i;
4306 if (port_low <= 0 || port_low > 65535 ||
4307 port_high <= 0 || port_high > 65535 ||
4308 port_low > port_high) {
4309 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4310 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004313 }
4314 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4315 for (i = 0; i < newsrv->sport_range->size; i++)
4316 newsrv->sport_range->ports[i] = port_low + i;
4317 }
4318
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004320 while (*(args[cur_arg])) {
4321 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004322#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4323#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004324 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4325 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4326 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004329 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004330#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004331 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004332 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004333 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004336 }
4337 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004338 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004339 newsrv->state |= SRV_TPROXY_CLI;
4340 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004341 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004342 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004343 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4344 char *name, *end;
4345
4346 name = args[cur_arg+1] + 7;
4347 while (isspace(*name))
4348 name++;
4349
4350 end = name;
4351 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4352 end++;
4353
4354 newsrv->state &= ~SRV_TPROXY_MASK;
4355 newsrv->state |= SRV_TPROXY_DYN;
4356 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4357 newsrv->bind_hdr_len = end - name;
4358 memcpy(newsrv->bind_hdr_name, name, end - name);
4359 newsrv->bind_hdr_name[end-name] = '\0';
4360 newsrv->bind_hdr_occ = -1;
4361
4362 /* now look for an occurrence number */
4363 while (isspace(*end))
4364 end++;
4365 if (*end == ',') {
4366 end++;
4367 name = end;
4368 if (*end == '-')
4369 end++;
4370 while (isdigit(*end))
4371 end++;
4372 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4373 }
4374
4375 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4376 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4377 " occurrences values smaller than %d.\n",
4378 file, linenum, MAX_HDR_HISTORY);
4379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
4381 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004382 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004383 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4384 if (!sk) {
4385 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
4388 }
4389 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004390 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004391 }
4392 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004393#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004394 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004395#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004396 cur_arg += 2;
4397 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004398#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004399 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004400 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004403#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4404 } /* "usesrc" */
4405
4406 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4407#ifdef SO_BINDTODEVICE
4408 if (!*args[cur_arg + 1]) {
4409 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4410 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413 }
4414 if (newsrv->iface_name)
4415 free(newsrv->iface_name);
4416
4417 newsrv->iface_name = strdup(args[cur_arg + 1]);
4418 newsrv->iface_len = strlen(newsrv->iface_name);
4419 global.last_checks |= LSTCHK_NETADM;
4420#else
4421 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4422 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004425#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 cur_arg += 2;
4427 continue;
4428 }
4429 /* this keyword in not an option of "source" */
4430 break;
4431 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004433 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004434 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4435 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004438 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004440 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004441 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 +01004442 file, linenum, newsrv->id);
4443 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004444 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 +01004445 file, linenum);
4446
Willy Tarreau93893792009-07-23 13:19:11 +02004447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 }
4450 }
4451
4452 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004453 if (newsrv->trackit) {
4454 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4455 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004458 }
4459
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004460 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4461 newsrv->check_port = newsrv->check_addr.sin_port;
4462
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4464 newsrv->check_port = realport; /* by default */
4465 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004466 /* not yet valid, because no port was set on
4467 * the server either. We'll check if we have
4468 * a known port on the first listener.
4469 */
4470 struct listener *l;
4471 l = curproxy->listen;
4472 if (l) {
4473 int port;
4474 port = (l->addr.ss_family == AF_INET6)
4475 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4476 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4477 newsrv->check_port = port;
4478 }
4479 }
4480 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4482 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004486
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004487 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004488 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004489 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4490 err_code |= ERR_ALERT | ERR_ABORT;
4491 goto out;
4492 }
4493
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004494 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 newsrv->state |= SRV_CHECKED;
4496 }
4497
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004498 if (!defsrv) {
4499 if (newsrv->state & SRV_BACKUP)
4500 curproxy->srv_bck++;
4501 else
4502 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004503
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004504 newsrv->prev_state = newsrv->state;
4505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
4507 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004508 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 int facility;
4510
4511 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4512 curproxy->logfac1 = global.logfac1;
4513 curproxy->logsrv1 = global.logsrv1;
4514 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004515 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 curproxy->logfac2 = global.logfac2;
4517 curproxy->logsrv2 = global.logsrv2;
4518 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004519 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 }
4521 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004522 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523
4524 facility = get_log_facility(args[2]);
4525 if (facility < 0) {
4526 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4527 exit(1);
4528 }
4529
4530 level = 7; /* max syslog level = debug */
4531 if (*(args[3])) {
4532 level = get_log_level(args[3]);
4533 if (level < 0) {
4534 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4535 exit(1);
4536 }
4537 }
4538
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004539 minlvl = 0; /* limit syslog level to this level (emerg) */
4540 if (*(args[4])) {
4541 minlvl = get_log_level(args[4]);
4542 if (level < 0) {
4543 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4544 exit(1);
4545 }
4546 }
4547
Robert Tsai81ae1952007-12-05 10:47:29 +01004548 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004549 struct sockaddr_un *sk = str2sun(args[1]);
4550 if (!sk) {
4551 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4552 args[1], (int)sizeof(sk->sun_path) - 1);
4553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
4555 }
4556 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004557 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004558 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004559 struct sockaddr_in *sk = str2sa(args[1]);
4560 if (!sk) {
4561 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
4564 }
4565 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004566 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004567 if (!logsrv.u.in.sin_port) {
4568 logsrv.u.in.sin_port =
4569 htons(SYSLOG_PORT);
4570 }
4571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572
4573 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004574 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 curproxy->logfac1 = facility;
4576 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004577 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 }
4579 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004580 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 curproxy->logfac2 = facility;
4582 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004583 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 }
4585 else {
4586 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 }
4590 }
4591 else {
4592 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4593 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
4597 }
4598 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004599 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004600 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004601
Willy Tarreau977b8e42006-12-29 14:19:17 +01004602 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004604
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004606 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4607 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004611
4612 /* we must first clear any optional default setting */
4613 curproxy->options &= ~PR_O_TPXY_MASK;
4614 free(curproxy->iface_name);
4615 curproxy->iface_name = NULL;
4616 curproxy->iface_len = 0;
4617
Willy Tarreaud5191e72010-02-09 20:50:45 +01004618 sk = str2sa(args[1]);
4619 if (!sk) {
4620 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
4623 }
4624 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004626
4627 cur_arg = 2;
4628 while (*(args[cur_arg])) {
4629 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004630#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4631#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004632 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4633 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4634 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004637 }
4638#endif
4639 if (!*args[cur_arg + 1]) {
4640 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4641 file, linenum, "usesrc");
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
4646 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004647 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004648 curproxy->options |= PR_O_TPXY_CLI;
4649 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004650 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004651 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004652 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4653 char *name, *end;
4654
4655 name = args[cur_arg+1] + 7;
4656 while (isspace(*name))
4657 name++;
4658
4659 end = name;
4660 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4661 end++;
4662
4663 curproxy->options &= ~PR_O_TPXY_MASK;
4664 curproxy->options |= PR_O_TPXY_DYN;
4665 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4666 curproxy->bind_hdr_len = end - name;
4667 memcpy(curproxy->bind_hdr_name, name, end - name);
4668 curproxy->bind_hdr_name[end-name] = '\0';
4669 curproxy->bind_hdr_occ = -1;
4670
4671 /* now look for an occurrence number */
4672 while (isspace(*end))
4673 end++;
4674 if (*end == ',') {
4675 end++;
4676 name = end;
4677 if (*end == '-')
4678 end++;
4679 while (isdigit(*end))
4680 end++;
4681 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4682 }
4683
4684 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4685 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4686 " occurrences values smaller than %d.\n",
4687 file, linenum, MAX_HDR_HISTORY);
4688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004691 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004692 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4693 if (!sk) {
4694 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
4697 }
4698 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700 }
4701 global.last_checks |= LSTCHK_NETADM;
4702#if !defined(CONFIG_HAP_LINUX_TPROXY)
4703 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004704#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004705#else /* no TPROXY support */
4706 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004707 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004710#endif
4711 cur_arg += 2;
4712 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004713 }
4714
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4716#ifdef SO_BINDTODEVICE
4717 if (!*args[cur_arg + 1]) {
4718 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4719 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004722 }
4723 if (curproxy->iface_name)
4724 free(curproxy->iface_name);
4725
4726 curproxy->iface_name = strdup(args[cur_arg + 1]);
4727 curproxy->iface_len = strlen(curproxy->iface_name);
4728 global.last_checks |= LSTCHK_NETADM;
4729#else
4730 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4731 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004734#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004735 cur_arg += 2;
4736 continue;
4737 }
4738 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4739 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004744 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4745 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4746 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004751 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4753 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004757
4758 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4759 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004760 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004761 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
4764 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004765 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4766 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004767 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004768 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 }
4771 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4773 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004774 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004775 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
4778 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4780 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004781 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004782 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 }
4785 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4787 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004788 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004792 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4794 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004795 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004797 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004798 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004799 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4801 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004802 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004803 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004804 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004805 }
4806 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004807 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4808 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004809 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004810 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004811 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004814 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4816 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004820
4821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4822 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004823 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
4827 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4829 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004830 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004831 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833 }
4834 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4836 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004837 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004838 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 }
4841 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4843 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004844 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004845 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 }
4848 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4850 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004851 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004852 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004855 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004856 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4857 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004858 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004859 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004860 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004863 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004864
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 if (curproxy == &defproxy) {
4866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004867 err_code |= ERR_ALERT | ERR_FATAL;
4868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004870 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004871 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 if (*(args[1]) == 0) {
4874 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004878
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004879 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4880 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4881 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4882 file, linenum, args[0]);
4883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
4885 }
4886 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4887 }
4888 else if (*args[2]) {
4889 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4890 file, linenum, args[0], args[2]);
4891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893 }
4894
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004895 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004896 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004897 wl->s = strdup(args[1]);
4898 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004899 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
4901 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4904 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004908
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4910 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004911 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
4915 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4917 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004918 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
4922 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4924 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004925 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
4929 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4932 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
4936
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4938 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004939 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
4943 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4945 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004946 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
4950 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4952 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004953 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
4957 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004958 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004959
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 if (curproxy == &defproxy) {
4961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004965 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 if (*(args[1]) == 0) {
4969 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004974 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4975 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4976 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4977 file, linenum, args[0]);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981 err_code |= warnif_cond_requires_req(cond, file, linenum);
4982 }
4983 else if (*args[2]) {
4984 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4985 file, linenum, args[0], args[2]);
4986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
4988 }
4989
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004990 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004991 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004992 wl->s = strdup(args[1]);
4993 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995 else if (!strcmp(args[0], "errorloc") ||
4996 !strcmp(args[0], "errorloc302") ||
4997 !strcmp(args[0], "errorloc303")) { /* error location */
4998 int errnum, errlen;
4999 char *err;
5000
Willy Tarreau977b8e42006-12-29 14:19:17 +01005001 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005003
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005005 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
5009
5010 errnum = atol(args[1]);
5011 if (!strcmp(args[0], "errorloc303")) {
5012 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5013 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5014 } else {
5015 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5016 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5017 }
5018
Willy Tarreau0f772532006-12-23 20:51:41 +01005019 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5020 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005021 chunk_destroy(&curproxy->errmsg[rc]);
5022 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005023 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005026
5027 if (rc >= HTTP_ERR_SIZE) {
5028 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5029 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 free(err);
5031 }
5032 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005033 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5034 int errnum, errlen, fd;
5035 char *err;
5036 struct stat stat;
5037
5038 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005040
5041 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005042 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005045 }
5046
5047 fd = open(args[2], O_RDONLY);
5048 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5049 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5050 file, linenum, args[2], args[1]);
5051 if (fd >= 0)
5052 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005055 }
5056
Willy Tarreau27a674e2009-08-17 07:23:33 +02005057 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005058 errlen = stat.st_size;
5059 } else {
5060 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005061 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005063 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005064 }
5065
5066 err = malloc(errlen); /* malloc() must succeed during parsing */
5067 errnum = read(fd, err, errlen);
5068 if (errnum != errlen) {
5069 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5070 file, linenum, args[2], args[1]);
5071 close(fd);
5072 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005075 }
5076 close(fd);
5077
5078 errnum = atol(args[1]);
5079 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5080 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005081 chunk_destroy(&curproxy->errmsg[rc]);
5082 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005083 break;
5084 }
5085 }
5086
5087 if (rc >= HTTP_ERR_SIZE) {
5088 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5089 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005091 free(err);
5092 }
5093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005095 struct cfg_kw_list *kwl;
5096 int index;
5097
5098 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5099 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5100 if (kwl->kw[index].section != CFG_LISTEN)
5101 continue;
5102 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5103 /* prepare error message just in case */
5104 snprintf(trash, sizeof(trash),
5105 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005106 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5107 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005108 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005111 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005112 else if (rc > 0) {
5113 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
5115 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005116 }
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005118 }
5119 }
5120 }
5121
Willy Tarreau6daf3432008-01-22 16:44:08 +01005122 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
Willy Tarreau93893792009-07-23 13:19:11 +02005126 out:
5127 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128}
5129
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005130int
5131cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5132{
5133
5134 int err_code = 0;
5135 const char *err;
5136
5137 if (!strcmp(args[0], "userlist")) { /* new userlist */
5138 struct userlist *newul;
5139
5140 if (!*args[1]) {
5141 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5142 file, linenum, args[0]);
5143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
5145 }
5146
5147 err = invalid_char(args[1]);
5148 if (err) {
5149 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5150 file, linenum, *err, args[0], args[1]);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
5154
5155 for (newul = userlist; newul; newul = newul->next)
5156 if (!strcmp(newul->name, args[1])) {
5157 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5158 file, linenum, args[1]);
5159 err_code |= ERR_WARN;
5160 goto out;
5161 }
5162
5163 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5164 if (!newul) {
5165 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5166 err_code |= ERR_ALERT | ERR_ABORT;
5167 goto out;
5168 }
5169
5170 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5171 newul->name = strdup(args[1]);
5172
5173 if (!newul->groupusers | !newul->name) {
5174 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5175 err_code |= ERR_ALERT | ERR_ABORT;
5176 goto out;
5177 }
5178
5179 newul->next = userlist;
5180 userlist = newul;
5181
5182 } else if (!strcmp(args[0], "group")) { /* new group */
5183 int cur_arg, i;
5184 const char *err;
5185
5186 if (!*args[1]) {
5187 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5188 file, linenum, args[0]);
5189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
5191 }
5192
5193 err = invalid_char(args[1]);
5194 if (err) {
5195 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5196 file, linenum, *err, args[0], args[1]);
5197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
5199 }
5200
5201 for(i = 0; i < userlist->grpcnt; i++)
5202 if (!strcmp(userlist->groups[i], args[1])) {
5203 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5204 file, linenum, args[1], userlist->name);
5205 err_code |= ERR_ALERT;
5206 goto out;
5207 }
5208
5209 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5210 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5211 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215
5216 cur_arg = 2;
5217
5218 while (*args[cur_arg]) {
5219 if (!strcmp(args[cur_arg], "users")) {
5220 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5221 cur_arg += 2;
5222 continue;
5223 } else {
5224 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5225 file, linenum, args[0]);
5226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
5228 }
5229 }
5230
5231 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5232 } else if (!strcmp(args[0], "user")) { /* new user */
5233 struct auth_users *newuser;
5234 int cur_arg;
5235
5236 if (!*args[1]) {
5237 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5238 file, linenum, args[0]);
5239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
5241 }
5242
5243 for (newuser = userlist->users; newuser; newuser = newuser->next)
5244 if (!strcmp(newuser->user, args[1])) {
5245 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5246 file, linenum, args[1], userlist->name);
5247 err_code |= ERR_ALERT;
5248 goto out;
5249 }
5250
5251 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5252 if (!newuser) {
5253 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5254 err_code |= ERR_ALERT | ERR_ABORT;
5255 goto out;
5256 }
5257
5258 newuser->user = strdup(args[1]);
5259
5260 newuser->next = userlist->users;
5261 userlist->users = newuser;
5262
5263 cur_arg = 2;
5264
5265 while (*args[cur_arg]) {
5266 if (!strcmp(args[cur_arg], "password")) {
5267#ifndef CONFIG_HAP_CRYPT
5268 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5269 file, linenum);
5270 err_code |= ERR_ALERT;
5271#endif
5272 newuser->pass = strdup(args[cur_arg + 1]);
5273 cur_arg += 2;
5274 continue;
5275 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5276 newuser->pass = strdup(args[cur_arg + 1]);
5277 newuser->flags |= AU_O_INSECURE;
5278 cur_arg += 2;
5279 continue;
5280 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005281 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005282 cur_arg += 2;
5283 continue;
5284 } else {
5285 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5286 file, linenum, args[0]);
5287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
5289 }
5290 }
5291 } else {
5292 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 }
5295
5296out:
5297 return err_code;
5298}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299
5300/*
5301 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005302 * Returns the error code, 0 if OK, or any combination of :
5303 * - ERR_ABORT: must abort ASAP
5304 * - ERR_FATAL: we can continue parsing but not start the service
5305 * - ERR_WARN: a warning has been emitted
5306 * - ERR_ALERT: an alert has been emitted
5307 * Only the two first ones can stop processing, the two others are just
5308 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005310int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005312 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 FILE *f;
5314 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005316 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 if ((f=fopen(file,"r")) == NULL)
5319 return -1;
5320
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005321 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005322 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005323 char *end;
5324 char *args[MAX_LINE_ARGS + 1];
5325 char *line = thisline;
5326
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 linenum++;
5328
5329 end = line + strlen(line);
5330
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005331 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5332 /* Check if we reached the limit and the last char is not \n.
5333 * Watch out for the last line without the terminating '\n'!
5334 */
5335 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005336 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005337 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005338 }
5339
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005341 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 line++;
5343
5344 arg = 0;
5345 args[arg] = line;
5346
5347 while (*line && arg < MAX_LINE_ARGS) {
5348 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5349 * C equivalent value. Other combinations left unchanged (eg: \1).
5350 */
5351 if (*line == '\\') {
5352 int skip = 0;
5353 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5354 *line = line[1];
5355 skip = 1;
5356 }
5357 else if (line[1] == 'r') {
5358 *line = '\r';
5359 skip = 1;
5360 }
5361 else if (line[1] == 'n') {
5362 *line = '\n';
5363 skip = 1;
5364 }
5365 else if (line[1] == 't') {
5366 *line = '\t';
5367 skip = 1;
5368 }
5369 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005370 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 unsigned char hex1, hex2;
5372 hex1 = toupper(line[2]) - '0';
5373 hex2 = toupper(line[3]) - '0';
5374 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5375 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5376 *line = (hex1<<4) + hex2;
5377 skip = 3;
5378 }
5379 else {
5380 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005381 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
5383 }
5384 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005385 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 end -= skip;
5387 }
5388 line++;
5389 }
5390 else if (*line == '#' || *line == '\n' || *line == '\r') {
5391 /* end of string, end of loop */
5392 *line = 0;
5393 break;
5394 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005395 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005397 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005398 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399 line++;
5400 args[++arg] = line;
5401 }
5402 else {
5403 line++;
5404 }
5405 }
5406
5407 /* empty line */
5408 if (!**args)
5409 continue;
5410
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005411 if (*line) {
5412 /* we had to stop due to too many args.
5413 * Let's terminate the string, print the offending part then cut the
5414 * last arg.
5415 */
5416 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5417 line++;
5418 *line = '\0';
5419
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005420 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005421 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005422 err_code |= ERR_ALERT | ERR_FATAL;
5423 args[arg] = line;
5424 }
5425
Willy Tarreau540abe42007-05-02 20:50:16 +02005426 /* zero out remaining args and ensure that at least one entry
5427 * is zeroed out.
5428 */
5429 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 args[arg] = line;
5431 }
5432
Willy Tarreau3842f002009-06-14 11:39:52 +02005433 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005434 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005435 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005436 for (arg=0; *args[arg+1]; arg++)
5437 args[arg] = args[arg+1]; // shift args after inversion
5438 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005439 else if (!strcmp(args[0], "default")) {
5440 kwm = KWM_DEF;
5441 for (arg=0; *args[arg+1]; arg++)
5442 args[arg] = args[arg+1]; // shift args after inversion
5443 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005444
Willy Tarreau3842f002009-06-14 11:39:52 +02005445 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5446 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005447 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005448 }
5449
Willy Tarreau977b8e42006-12-29 14:19:17 +01005450 if (!strcmp(args[0], "listen") ||
5451 !strcmp(args[0], "frontend") ||
5452 !strcmp(args[0], "backend") ||
5453 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005454 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005456 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005457 cursection = strdup(args[0]);
5458 }
5459 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005461 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005462 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005463 }
5464 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005465 confsect = CFG_USERLIST;
5466 free(cursection);
5467 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005468 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005469 else if (!strcmp(args[0], "peers")) {
5470 confsect = CFG_PEERS;
5471 free(cursection);
5472 cursection = strdup(args[0]);
5473 }
5474
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 /* else it's a section keyword */
5476
5477 switch (confsect) {
5478 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005479 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 break;
5481 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005482 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005484 case CFG_USERLIST:
5485 err_code |= cfg_parse_users(file, linenum, args, kwm);
5486 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005487 case CFG_PEERS:
5488 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5489 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005491 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005492 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005494
5495 if (err_code & ERR_ABORT)
5496 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005498 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005499 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005501 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005502}
5503
Willy Tarreaubb925012009-07-23 13:36:36 +02005504/*
5505 * Returns the error code, 0 if OK, or any combination of :
5506 * - ERR_ABORT: must abort ASAP
5507 * - ERR_FATAL: we can continue parsing but not start the service
5508 * - ERR_WARN: a warning has been emitted
5509 * - ERR_ALERT: an alert has been emitted
5510 * Only the two first ones can stop processing, the two others are just
5511 * indicators.
5512 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005513int check_config_validity()
5514{
5515 int cfgerr = 0;
5516 struct proxy *curproxy = NULL;
5517 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005518 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005519 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005520 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521
5522 /*
5523 * Now, check for the integrity of all that we have collected.
5524 */
5525
5526 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005527 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005529 /* first, we will invert the proxy list order */
5530 curproxy = NULL;
5531 while (proxy) {
5532 struct proxy *next;
5533
5534 next = proxy->next;
5535 proxy->next = curproxy;
5536 curproxy = proxy;
5537 if (!next)
5538 break;
5539 proxy = next;
5540 }
5541
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005543 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546 }
5547
5548 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005549 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005550 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005551 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005552 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005553 unsigned int next_id;
5554
5555 if (!curproxy->uuid) {
5556 /* proxy ID not set, use automatic numbering with first
5557 * spare entry starting with next_pxid.
5558 */
5559 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5560 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5561 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005562 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005563 next_pxid++;
5564
Willy Tarreau55ea7572007-06-17 19:56:27 +02005565
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005567 /* ensure we don't keep listeners uselessly bound */
5568 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 curproxy = curproxy->next;
5570 continue;
5571 }
5572
Willy Tarreauff01a212009-03-15 13:46:16 +01005573 switch (curproxy->mode) {
5574 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005575 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005576 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005577 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5578 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005579 cfgerr++;
5580 }
5581
5582 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 Warning("config : servers will be ignored for %s '%s'.\n",
5584 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005585 break;
5586
5587 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005588 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005589 break;
5590
5591 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005592 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005593 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005594 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5595 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005596 cfgerr++;
5597 }
5598 break;
5599 }
5600
5601 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005602 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5603 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 cfgerr++;
5605 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005606
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005607 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005608 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005609 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005610 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5611 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005612 cfgerr++;
5613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005615 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005616 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5617 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 cfgerr++;
5619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005621 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005622 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5623 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005624 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005625 }
5626 }
5627 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5628 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5629 /* If no LB algo is set in a backend, and we're not in
5630 * transparent mode, dispatch mode nor proxy mode, we
5631 * want to use balance roundrobin by default.
5632 */
5633 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5634 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 }
5636 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005637
Willy Tarreau82936582007-11-30 15:20:09 +01005638 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5639 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005640 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5641 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005642 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005643 }
5644
Willy Tarreauef781042010-01-27 11:53:01 +01005645 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5646 curproxy->options &= ~PR_O2_CHK_SNDST;
5647 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5648 "send-state", proxy_type_str(curproxy), curproxy->id);
5649 err_code |= ERR_WARN;
5650 }
5651
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005652 /* if a default backend was specified, let's find it */
5653 if (curproxy->defbe.name) {
5654 struct proxy *target;
5655
Alex Williams96532db2009-11-01 21:27:13 -05005656 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005657 if (!target) {
5658 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5659 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005660 cfgerr++;
5661 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005662 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5663 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005664 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005665 } else {
5666 free(curproxy->defbe.name);
5667 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005668 /* we force the backend to be present on at least all of
5669 * the frontend's processes.
5670 */
5671 target->bind_proc = curproxy->bind_proc ?
5672 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
5674 }
5675
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005676 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005677 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5678 /* map jump target for ACT_SETBE in req_rep chain */
5679 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005680 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005681 struct proxy *target;
5682
Willy Tarreaua496b602006-12-17 23:15:24 +01005683 if (exp->action != ACT_SETBE)
5684 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005685
Alex Williams96532db2009-11-01 21:27:13 -05005686 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005687 if (!target) {
5688 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5689 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005690 cfgerr++;
5691 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005692 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5693 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005694 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005695 } else {
5696 free((void *)exp->replace);
5697 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005698 /* we force the backend to be present on at least all of
5699 * the frontend's processes.
5700 */
5701 target->bind_proc = curproxy->bind_proc ?
5702 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005703 }
5704 }
5705 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005706
5707 /* find the target proxy for 'use_backend' rules */
5708 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005709 struct proxy *target;
5710
Alex Williams96532db2009-11-01 21:27:13 -05005711 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005712
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005713 if (!target) {
5714 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5715 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005716 cfgerr++;
5717 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005718 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5719 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005720 cfgerr++;
5721 } else {
5722 free((void *)rule->be.name);
5723 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005724 /* we force the backend to be present on at least all of
5725 * the frontend's processes.
5726 */
5727 target->bind_proc = curproxy->bind_proc ?
5728 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005729 }
5730 }
5731
Emeric Brunb982a3d2010-01-04 15:45:53 +01005732 /* find the target table for 'stick' rules */
5733 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5734 struct proxy *target;
5735
Emeric Brun1d33b292010-01-04 15:47:17 +01005736 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5737 if (mrule->flags & STK_IS_STORE)
5738 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5739
Emeric Brunb982a3d2010-01-04 15:45:53 +01005740 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005741 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005742 else
5743 target = curproxy;
5744
5745 if (!target) {
5746 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5747 curproxy->id, mrule->table.name);
5748 cfgerr++;
5749 }
5750 else if (target->table.size == 0) {
5751 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5752 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5753 cfgerr++;
5754 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005755 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5757 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5758 cfgerr++;
5759 }
5760 else {
5761 free((void *)mrule->table.name);
5762 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005763 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005764 }
5765 }
5766
5767 /* find the target table for 'store response' rules */
5768 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5769 struct proxy *target;
5770
Emeric Brun1d33b292010-01-04 15:47:17 +01005771 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5772
Emeric Brunb982a3d2010-01-04 15:45:53 +01005773 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005774 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005775 else
5776 target = curproxy;
5777
5778 if (!target) {
5779 Alert("Proxy '%s': unable to find store table '%s'.\n",
5780 curproxy->id, mrule->table.name);
5781 cfgerr++;
5782 }
5783 else if (target->table.size == 0) {
5784 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5785 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5786 cfgerr++;
5787 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005788 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005789 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5790 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5791 cfgerr++;
5792 }
5793 else {
5794 free((void *)mrule->table.name);
5795 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005796 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005797 }
5798 }
5799
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005800 /* find the target table for 'tcp-request' layer 4 rules */
5801 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5802 struct proxy *target;
5803
Willy Tarreau56123282010-08-06 19:06:56 +02005804 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005805 continue;
5806
5807 if (trule->act_prm.trk_ctr.table.n)
5808 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5809 else
5810 target = curproxy;
5811
5812 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005813 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5814 curproxy->id, trule->act_prm.trk_ctr.table.n,
5815 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005816 cfgerr++;
5817 }
5818 else if (target->table.size == 0) {
5819 Alert("Proxy '%s': table '%s' used but not configured.\n",
5820 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5821 cfgerr++;
5822 }
5823 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005824 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 +02005825 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5826 cfgerr++;
5827 }
5828 else {
5829 free(trule->act_prm.trk_ctr.table.n);
5830 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005831 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005832 * to pass a list of counters to track and allocate them right here using
5833 * stktable_alloc_data_type().
5834 */
5835 }
5836 }
5837
Willy Tarreaud1f96522010-08-03 19:34:32 +02005838 /* find the target table for 'tcp-request' layer 6 rules */
5839 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5840 struct proxy *target;
5841
Willy Tarreau56123282010-08-06 19:06:56 +02005842 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005843 continue;
5844
5845 if (trule->act_prm.trk_ctr.table.n)
5846 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5847 else
5848 target = curproxy;
5849
5850 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005851 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5852 curproxy->id, trule->act_prm.trk_ctr.table.n,
5853 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005854 cfgerr++;
5855 }
5856 else if (target->table.size == 0) {
5857 Alert("Proxy '%s': table '%s' used but not configured.\n",
5858 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5859 cfgerr++;
5860 }
5861 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005862 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 +02005863 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5864 cfgerr++;
5865 }
5866 else {
5867 free(trule->act_prm.trk_ctr.table.n);
5868 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005869 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005870 * to pass a list of counters to track and allocate them right here using
5871 * stktable_alloc_data_type().
5872 */
5873 }
5874 }
5875
Emeric Brun32da3c42010-09-23 18:39:19 +02005876 if (curproxy->table.peers.name) {
5877 struct peers *curpeers = peers;
5878
5879 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5880 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5881 free((void *)curproxy->table.peers.name);
5882 curproxy->table.peers.p = peers;
5883 break;
5884 }
5885 }
5886
5887 if (!curpeers) {
5888 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5889 curproxy->id, curproxy->table.peers.name);
5890 cfgerr++;
5891 }
5892 else if (!curpeers->peers_fe) {
5893 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5894 curproxy->id, curpeers->id);
5895 cfgerr++;
5896 }
5897 }
5898
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005899 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5900 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005901 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5902 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5903 "proxy", curproxy->id);
5904 cfgerr++;
5905 goto out_uri_auth_compat;
5906 }
5907
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005908 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005909 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005910 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005911 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005912
Willy Tarreau95fa4692010-02-01 13:05:50 +01005913 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5914 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005915
5916 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005917 uri_auth_compat_req[i++] = "realm";
5918 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5919 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005920
Willy Tarreau95fa4692010-02-01 13:05:50 +01005921 uri_auth_compat_req[i++] = "unless";
5922 uri_auth_compat_req[i++] = "{";
5923 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5924 uri_auth_compat_req[i++] = "}";
5925 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005926
Willy Tarreau95fa4692010-02-01 13:05:50 +01005927 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5928 if (!req_acl) {
5929 cfgerr++;
5930 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005931 }
5932
Willy Tarreau95fa4692010-02-01 13:05:50 +01005933 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5934
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005935 if (curproxy->uri_auth->auth_realm) {
5936 free(curproxy->uri_auth->auth_realm);
5937 curproxy->uri_auth->auth_realm = NULL;
5938 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005939
5940 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005941 }
5942out_uri_auth_compat:
5943
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005944 cfgerr += acl_find_targets(curproxy);
5945
Willy Tarreau2738a142006-07-08 17:28:09 +02005946 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005947 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005948 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005949 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005950 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005951 " | While not properly invalid, you will certainly encounter various problems\n"
5952 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005953 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005954 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005955 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005956 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005957
Willy Tarreau1fa31262007-12-03 00:36:16 +01005958 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5959 * We must still support older configurations, so let's find out whether those
5960 * parameters have been set or must be copied from contimeouts.
5961 */
5962 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005963 if (!curproxy->timeout.tarpit ||
5964 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005965 /* tarpit timeout not set. We search in the following order:
5966 * default.tarpit, curr.connect, default.connect.
5967 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005968 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005969 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005970 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005971 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005972 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005973 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005974 }
5975 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005976 (!curproxy->timeout.queue ||
5977 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005978 /* queue timeout not set. We search in the following order:
5979 * default.queue, curr.connect, default.connect.
5980 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005981 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005982 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005983 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005984 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005985 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005986 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005987 }
5988 }
5989
Willy Tarreau07a54902010-03-29 18:33:29 +02005990 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005991 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5992 curproxy->check_req = (char *)malloc(curproxy->check_len);
5993 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005994 }
5995
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005996 /* The small pools required for the capture lists */
5997 if (curproxy->nb_req_cap)
5998 curproxy->req_cap_pool = create_pool("ptrcap",
5999 curproxy->nb_req_cap * sizeof(char *),
6000 MEM_F_SHARED);
6001 if (curproxy->nb_rsp_cap)
6002 curproxy->rsp_cap_pool = create_pool("ptrcap",
6003 curproxy->nb_rsp_cap * sizeof(char *),
6004 MEM_F_SHARED);
6005
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006006 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6007 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6008 MEM_F_SHARED);
6009
Willy Tarreau86034312006-12-29 00:10:33 +01006010 /* for backwards compatibility with "listen" instances, if
6011 * fullconn is not set but maxconn is set, then maxconn
6012 * is used.
6013 */
6014 if (!curproxy->fullconn)
6015 curproxy->fullconn = curproxy->maxconn;
6016
Willy Tarreaubaaee002006-06-26 02:48:02 +02006017 /* first, we will invert the servers list order */
6018 newsrv = NULL;
6019 while (curproxy->srv) {
6020 struct server *next;
6021
6022 next = curproxy->srv->next;
6023 curproxy->srv->next = newsrv;
6024 newsrv = curproxy->srv;
6025 if (!next)
6026 break;
6027 curproxy->srv = next;
6028 }
6029
Willy Tarreaudd701652010-05-25 23:03:02 +02006030 /* assign automatic UIDs to servers which don't have one yet */
6031 next_id = 1;
6032 newsrv = curproxy->srv;
6033 while (newsrv != NULL) {
6034 if (!newsrv->puid) {
6035 /* server ID not set, use automatic numbering with first
6036 * spare entry starting with next_svid.
6037 */
6038 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6039 newsrv->conf.id.key = newsrv->puid = next_id;
6040 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6041 }
6042 next_id++;
6043 newsrv = newsrv->next;
6044 }
6045
Willy Tarreau20697042007-11-15 23:26:18 +01006046 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006047 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006049 /* We have to initialize the server lookup mechanism depending
6050 * on what LB algorithm was choosen.
6051 */
6052
6053 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6054 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6055 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006056 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6057 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6058 init_server_map(curproxy);
6059 } else {
6060 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6061 fwrr_init_server_groups(curproxy);
6062 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006063 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006064
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006065 case BE_LB_KIND_LC:
6066 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006067 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006068 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006069
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006070 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006071 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6072 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6073 chash_init_server_tree(curproxy);
6074 } else {
6075 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6076 init_server_map(curproxy);
6077 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006078 break;
6079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006080
6081 if (curproxy->options & PR_O_LOGASAP)
6082 curproxy->to_log &= ~LW_BYTES;
6083
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006084 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6085 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6086 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6087 proxy_type_str(curproxy), curproxy->id);
6088 err_code |= ERR_WARN;
6089 }
6090
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006091 if (curproxy->mode != PR_MODE_HTTP) {
6092 int optnum;
6093
6094 if (curproxy->options & PR_O_COOK_ANY) {
6095 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6096 proxy_type_str(curproxy), curproxy->id);
6097 err_code |= ERR_WARN;
6098 }
6099
6100 if (curproxy->uri_auth) {
6101 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6102 proxy_type_str(curproxy), curproxy->id);
6103 err_code |= ERR_WARN;
6104 curproxy->uri_auth = NULL;
6105 }
6106
6107 if (curproxy->options & PR_O_FWDFOR) {
6108 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6109 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6110 err_code |= ERR_WARN;
6111 curproxy->options &= ~PR_O_FWDFOR;
6112 }
6113
6114 if (curproxy->options & PR_O_ORGTO) {
6115 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6116 "originalto", proxy_type_str(curproxy), curproxy->id);
6117 err_code |= ERR_WARN;
6118 curproxy->options &= ~PR_O_ORGTO;
6119 }
6120
6121 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6122 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6123 (curproxy->cap & cfg_opts[optnum].cap) &&
6124 (curproxy->options & cfg_opts[optnum].val)) {
6125 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6126 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6127 err_code |= ERR_WARN;
6128 curproxy->options &= ~cfg_opts[optnum].val;
6129 }
6130 }
6131
6132 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6133 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6134 (curproxy->cap & cfg_opts2[optnum].cap) &&
6135 (curproxy->options2 & cfg_opts2[optnum].val)) {
6136 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6137 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6138 err_code |= ERR_WARN;
6139 curproxy->options2 &= ~cfg_opts2[optnum].val;
6140 }
6141 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006142
Willy Tarreauefa5f512010-03-30 20:13:29 +02006143#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006144 if (curproxy->bind_hdr_occ) {
6145 curproxy->bind_hdr_occ = 0;
6146 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6147 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6148 err_code |= ERR_WARN;
6149 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006150#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006151 }
6152
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006154 * ensure that we're not cross-dressing a TCP server into HTTP.
6155 */
6156 newsrv = curproxy->srv;
6157 while (newsrv != NULL) {
6158 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006159 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6160 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006161 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006162 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006163
Willy Tarreauefa5f512010-03-30 20:13:29 +02006164#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006165 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6166 newsrv->bind_hdr_occ = 0;
6167 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6168 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6169 err_code |= ERR_WARN;
6170 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006171#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006172 newsrv = newsrv->next;
6173 }
6174
6175 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 * If this server supports a maxconn parameter, it needs a dedicated
6177 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006178 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 */
6180 newsrv = curproxy->srv;
6181 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006182 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 /* Only 'minconn' was specified, or it was higher than or equal
6184 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6185 * this will avoid further useless expensive computations.
6186 */
6187 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006188 } else if (newsrv->maxconn && !newsrv->minconn) {
6189 /* minconn was not specified, so we set it to maxconn */
6190 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006191 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006192 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6193 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006194 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006195 }
6196
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006197 if (newsrv->trackit) {
6198 struct proxy *px;
6199 struct server *srv;
6200 char *pname, *sname;
6201
6202 pname = newsrv->trackit;
6203 sname = strrchr(pname, '/');
6204
6205 if (sname)
6206 *sname++ = '\0';
6207 else {
6208 sname = pname;
6209 pname = NULL;
6210 }
6211
6212 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006213 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006214 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006215 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6216 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006217 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006218 cfgerr++;
6219 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006220 }
6221 } else
6222 px = curproxy;
6223
6224 srv = findserver(px, sname);
6225 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006226 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6227 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006228 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006229 cfgerr++;
6230 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006231 }
6232
6233 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006234 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006235 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006236 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006237 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006238 cfgerr++;
6239 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006240 }
6241
6242 if (curproxy != px &&
6243 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006244 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006245 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006246 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006247 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006248 cfgerr++;
6249 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006250 }
6251
6252 newsrv->tracked = srv;
6253 newsrv->tracknext = srv->tracknext;
6254 srv->tracknext = newsrv;
6255
6256 free(newsrv->trackit);
6257 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006258 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006259 newsrv = newsrv->next;
6260 }
6261
Willy Tarreauc1a21672009-08-16 22:37:44 +02006262 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006263 curproxy->accept = frontend_accept;
6264
Willy Tarreauc1a21672009-08-16 22:37:44 +02006265 if (curproxy->tcp_req.inspect_delay ||
6266 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006267 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006268
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006269 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006270 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006271 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006272 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006273
6274 /* both TCP and HTTP must check switching rules */
6275 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6276 }
6277
6278 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006279 if (curproxy->tcp_req.inspect_delay ||
6280 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6281 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6282
Emeric Brun97679e72010-09-23 17:56:44 +02006283 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6284 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6285
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006286 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006287 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006288 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006289 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006290
6291 /* If the backend does requires RDP cookie persistence, we have to
6292 * enable the corresponding analyser.
6293 */
6294 if (curproxy->options2 & PR_O2_RDPC_PRST)
6295 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6296 }
6297
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006298 listener = NULL;
6299 while (curproxy->listen) {
6300 struct listener *next;
6301
6302 next = curproxy->listen->next;
6303 curproxy->listen->next = listener;
6304 listener = curproxy->listen;
6305
6306 if (!next)
6307 break;
6308
6309 curproxy->listen = next;
6310 }
6311
Willy Tarreaue6b98942007-10-29 01:09:36 +01006312 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006313 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006314 listener = curproxy->listen;
6315 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006316 if (!listener->luid) {
6317 /* listener ID not set, use automatic numbering with first
6318 * spare entry starting with next_luid.
6319 */
6320 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6321 listener->conf.id.key = listener->luid = next_id;
6322 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006323 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006324 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006325
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006326 /* enable separate counters */
6327 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6328 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6329 if (!listener->name) {
6330 sprintf(trash, "sock-%d", listener->luid);
6331 listener->name = strdup(trash);
6332 }
6333 }
6334
Willy Tarreaue6b98942007-10-29 01:09:36 +01006335 if (curproxy->options & PR_O_TCP_NOLING)
6336 listener->options |= LI_O_NOLINGER;
6337 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006338 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006339 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006340 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006341 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006342 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006343 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006344
Willy Tarreau8a956912010-10-15 14:27:08 +02006345 if (listener->options & LI_O_ACC_PROXY)
6346 listener->analysers |= AN_REQ_DECODE_PROXY;
6347
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006348 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6349 listener->options |= LI_O_TCP_RULES;
6350
Willy Tarreaude3041d2010-05-31 10:56:17 +02006351 if (curproxy->mon_mask.s_addr)
6352 listener->options |= LI_O_CHK_MONNET;
6353
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006354 /* smart accept mode is automatic in HTTP mode */
6355 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6356 (curproxy->mode == PR_MODE_HTTP &&
6357 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6358 listener->options |= LI_O_NOQUICKACK;
6359
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006360 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006361 listener = listener->next;
6362 }
6363
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006364 /* Check multi-process mode compatibility for the current proxy */
6365 if (global.nbproc > 1) {
6366 int nbproc = 0;
6367 if (curproxy->bind_proc) {
6368 int proc;
6369 for (proc = 0; proc < global.nbproc; proc++) {
6370 if (curproxy->bind_proc & (1 << proc)) {
6371 nbproc++;
6372 }
6373 }
6374 } else {
6375 nbproc = global.nbproc;
6376 }
6377 if (curproxy->table.peers.name) {
6378 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6379 curproxy->id);
6380 cfgerr++;
6381 }
6382 if (nbproc > 1) {
6383 if (curproxy->uri_auth) {
6384 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6385 curproxy->id);
6386 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6387 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6388 curproxy->id);
6389 }
6390 }
6391 if (curproxy->appsession_name) {
6392 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6393 curproxy->id);
6394 }
6395 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6396 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6397 curproxy->id);
6398 }
6399 }
6400 }
6401
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 curproxy = curproxy->next;
6403 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006404
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006405 /* Check multi-process mode compatibility */
6406 if (global.nbproc > 1) {
6407 if (global.stats_fe) {
6408 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6409 }
6410 }
6411
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006412 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6413 struct auth_users *curuser;
6414 int g;
6415
6416 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6417 unsigned int group_mask = 0;
6418 char *group = NULL;
6419
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006420 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006421 continue;
6422
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006423 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006424
6425 for (g = 0; g < curuserlist->grpcnt; g++)
6426 if (!strcmp(curuserlist->groups[g], group))
6427 break;
6428
6429 if (g == curuserlist->grpcnt) {
6430 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6431 curuserlist->name, group, curuser->user);
6432 err_code |= ERR_ALERT | ERR_FATAL;
6433 goto out;
6434 }
6435
6436 group_mask |= (1 << g);
6437 }
6438
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006439 free(curuser->u.groups);
6440 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006441 }
6442
6443 for (g = 0; g < curuserlist->grpcnt; g++) {
6444 char *user = NULL;
6445
6446 if (!curuserlist->groupusers[g])
6447 continue;
6448
6449 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6450 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6451 if (!strcmp(curuser->user, user))
6452 break;
6453
6454 if (!curuser) {
6455 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6456 curuserlist->name, user, curuserlist->groups[g]);
6457 err_code |= ERR_ALERT | ERR_FATAL;
6458 goto out;
6459 }
6460
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006461 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006462 }
6463
6464 free(curuserlist->groupusers[g]);
6465 }
6466
6467 free(curuserlist->groupusers);
6468
6469#ifdef DEBUG_AUTH
6470 for (g = 0; g < curuserlist->grpcnt; g++) {
6471 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6472
6473 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6474 if (curuser->group_mask & (1 << g))
6475 fprintf(stderr, " %s", curuser->user);
6476 }
6477
6478 fprintf(stderr, "\n");
6479 }
6480#endif
6481
6482 }
6483
Willy Tarreau056f5682010-06-06 15:51:11 +02006484 /* initialize stick-tables on backend capable proxies. This must not
6485 * be done earlier because the data size may be discovered while parsing
6486 * other proxies.
6487 */
6488 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006489 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006490
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006491 /*
6492 * Recount currently required checks.
6493 */
6494
6495 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6496 int optnum;
6497
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006498 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6499 if (curproxy->options & cfg_opts[optnum].val)
6500 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006501
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006502 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6503 if (curproxy->options2 & cfg_opts2[optnum].val)
6504 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006505 }
6506
Willy Tarreaubb925012009-07-23 13:36:36 +02006507 if (cfgerr > 0)
6508 err_code |= ERR_ALERT | ERR_FATAL;
6509 out:
6510 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511}
6512
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006513/*
6514 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6515 * parsing sessions.
6516 */
6517void cfg_register_keywords(struct cfg_kw_list *kwl)
6518{
6519 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6520}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006521
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006522/*
6523 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6524 */
6525void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6526{
6527 LIST_DEL(&kwl->list);
6528 LIST_INIT(&kwl->list);
6529}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530
6531/*
6532 * Local variables:
6533 * c-indent-level: 8
6534 * c-basic-offset: 8
6535 * End:
6536 */