blob: dd266af320fe1ad48e2eb8a032989a7efa4aad78 [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;
1434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 global.maxsock++;
1436 }
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;
1636 }
1637
Emeric Bruned760922010-10-22 17:59:25 +02001638 /* Set default global rights and owner for unix bind */
1639 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1640 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1641 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001642 cur_arg = 2;
1643 while (*(args[cur_arg])) {
1644 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1645#ifdef SO_BINDTODEVICE
1646 struct listener *l;
1647
Emeric Bruned760922010-10-22 17:59:25 +02001648 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1649 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1650 file, linenum, args[0], args[cur_arg]);
1651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
1653 }
1654
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001655 if (!*args[cur_arg + 1]) {
1656 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1657 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001660 }
1661
1662 for (l = curproxy->listen; l != last_listen; l = l->next)
1663 l->interface = strdup(args[cur_arg + 1]);
1664
1665 global.last_checks |= LSTCHK_NETADM;
1666
1667 cur_arg += 2;
1668 continue;
1669#else
1670 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1671 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_FATAL;
1673 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001674#endif
1675 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001676 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1677#ifdef TCP_MAXSEG
1678 struct listener *l;
1679 int mss;
1680
Emeric Bruned760922010-10-22 17:59:25 +02001681 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1682 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1683 file, linenum, args[0], args[cur_arg]);
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687
Willy Tarreaube1b9182009-06-14 18:48:19 +02001688 if (!*args[cur_arg + 1]) {
1689 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1690 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001693 }
1694
Willy Tarreau48a7e722010-12-24 15:26:39 +01001695 mss = atoi(args[cur_arg + 1]);
1696 if (!mss || abs(mss) > 65535) {
1697 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001701 }
1702
1703 for (l = curproxy->listen; l != last_listen; l = l->next)
1704 l->maxseg = mss;
1705
1706 cur_arg += 2;
1707 continue;
1708#else
1709 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1710 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001713#endif
1714 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001715
1716 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1717#ifdef TCP_DEFER_ACCEPT
1718 struct listener *l;
1719
1720 for (l = curproxy->listen; l != last_listen; l = l->next)
1721 l->options |= LI_O_DEF_ACCEPT;
1722
1723 cur_arg ++;
1724 continue;
1725#else
1726 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1727 file, linenum, args[0], args[cur_arg]);
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730#endif
1731 }
1732
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001733 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001735 struct listener *l;
1736
Emeric Bruned760922010-10-22 17:59:25 +02001737 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1738 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1739 file, linenum, args[0], args[cur_arg]);
1740 err_code |= ERR_ALERT | ERR_FATAL;
1741 goto out;
1742 }
1743
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001744 for (l = curproxy->listen; l != last_listen; l = l->next)
1745 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001746
1747 cur_arg ++;
1748 continue;
1749#else
1750 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1751 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001754#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001755 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001756
Willy Tarreau8a956912010-10-15 14:27:08 +02001757 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1758 struct listener *l;
1759
1760 for (l = curproxy->listen; l != last_listen; l = l->next)
1761 l->options |= LI_O_ACC_PROXY;
1762
1763 cur_arg ++;
1764 continue;
1765 }
1766
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001767 if (!strcmp(args[cur_arg], "name")) {
1768 struct listener *l;
1769
1770 for (l = curproxy->listen; l != last_listen; l = l->next)
1771 l->name = strdup(args[cur_arg + 1]);
1772
1773 cur_arg += 2;
1774 continue;
1775 }
1776
1777 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001778 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779 struct listener *l;
1780
1781 if (curproxy->listen->next != last_listen) {
1782 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1783 file, linenum, args[cur_arg]);
1784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
1786 }
1787
1788 if (!*args[cur_arg + 1]) {
1789 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1790 file, linenum, args[cur_arg]);
1791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
1793 }
1794
1795 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001796 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001797
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001798 if (curproxy->listen->luid <= 0) {
1799 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001800 file, linenum);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001805 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1806 if (node) {
1807 l = container_of(node, struct listener, conf.id);
1808 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1809 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1814
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001815 cur_arg += 2;
1816 continue;
1817 }
1818
Emeric Bruned760922010-10-22 17:59:25 +02001819 if (!strcmp(args[cur_arg], "mode")) {
1820
1821 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1822 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1823 file, linenum, args[0], args[cur_arg]);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1829
1830 cur_arg += 2;
1831 continue;
1832 }
1833
1834 if (!strcmp(args[cur_arg], "uid")) {
1835
1836 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1837 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1838 file, linenum, args[0], args[cur_arg]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842
1843 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1844 cur_arg += 2;
1845 continue;
1846 }
1847
1848 if (!strcmp(args[cur_arg], "gid")) {
1849
1850 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1851 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1852 file, linenum, args[0], args[cur_arg]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
1857 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1858 cur_arg += 2;
1859 continue;
1860 }
1861
1862 if (!strcmp(args[cur_arg], "user")) {
1863 struct passwd *user;
1864
1865 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1866 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1867 file, linenum, args[0], args[cur_arg]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870 }
1871 user = getpwnam(args[cur_arg + 1]);
1872 if (!user) {
1873 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1874 file, linenum, args[0], args[cur_arg + 1 ]);
1875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
1877 }
1878
1879 curproxy->listen->perm.ux.uid = user->pw_uid;
1880 cur_arg += 2;
1881 continue;
1882 }
1883
1884 if (!strcmp(args[cur_arg], "group")) {
1885 struct group *group;
1886
1887 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1888 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1889 file, linenum, args[0], args[cur_arg]);
1890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
1892 }
1893 group = getgrnam(args[cur_arg + 1]);
1894 if (!group) {
1895 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1896 file, linenum, args[0], args[cur_arg + 1 ]);
1897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
1899 }
1900
1901 curproxy->listen->perm.ux.gid = group->gr_gid;
1902 cur_arg += 2;
1903 continue;
1904 }
1905
Willy Tarreau8a956912010-10-15 14:27:08 +02001906 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 +01001907 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 global.maxsock++;
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 Tarreau61d18892009-03-31 10:49:21 +02002647 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002648 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002649 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 struct switching_rule *rule;
2651
Willy Tarreaub099aca2008-10-12 17:26:37 +02002652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002656 }
2657
Willy Tarreau55ea7572007-06-17 19:56:27 +02002658 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002660
2661 if (*(args[1]) == 0) {
2662 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002665 }
2666
Willy Tarreauef6494c2010-01-28 17:12:36 +01002667 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002668 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002672 }
2673
Willy Tarreauef6494c2010-01-28 17:12:36 +01002674 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002675 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002676 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002679 }
2680
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002681 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002682
Willy Tarreau55ea7572007-06-17 19:56:27 +02002683 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2684 rule->cond = cond;
2685 rule->be.name = strdup(args[1]);
2686 LIST_INIT(&rule->list);
2687 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2688 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002689 else if ((!strcmp(args[0], "force-persist")) ||
2690 (!strcmp(args[0], "ignore-persist"))) {
2691 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002692
2693 if (curproxy == &defproxy) {
2694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698
2699 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2700 err_code |= ERR_WARN;
2701
Willy Tarreauef6494c2010-01-28 17:12:36 +01002702 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2704 file, linenum, args[0]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708
Willy Tarreauef6494c2010-01-28 17:12:36 +01002709 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002710 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2711 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
2714 }
2715
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002716 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002717
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002718 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002719 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002720 if (!strcmp(args[0], "force-persist")) {
2721 rule->type = PERSIST_TYPE_FORCE;
2722 } else {
2723 rule->type = PERSIST_TYPE_IGNORE;
2724 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002725 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002726 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002727 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002728 else if (!strcmp(args[0], "stick-table")) {
2729 int myidx = 1;
2730
Emeric Brun32da3c42010-09-23 18:39:19 +02002731 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002732 curproxy->table.type = (unsigned int)-1;
2733 while (*args[myidx]) {
2734 const char *err;
2735
2736 if (strcmp(args[myidx], "size") == 0) {
2737 myidx++;
2738 if (!*(args[myidx])) {
2739 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2740 file, linenum, args[myidx-1]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2745 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2746 file, linenum, *err, args[myidx-1]);
2747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002750 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002751 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002752 else if (strcmp(args[myidx], "peers") == 0) {
2753 myidx++;
2754 if (!*(args[myidx])) {
2755 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2756 file, linenum, args[myidx-1]);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
2760 curproxy->table.peers.name = strdup(args[myidx++]);
2761 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002762 else if (strcmp(args[myidx], "expire") == 0) {
2763 myidx++;
2764 if (!*(args[myidx])) {
2765 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2766 file, linenum, args[myidx-1]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
2770 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2771 if (err) {
2772 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2773 file, linenum, *err, args[myidx-1]);
2774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
2776 }
2777 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002778 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002779 }
2780 else if (strcmp(args[myidx], "nopurge") == 0) {
2781 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002782 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002783 }
2784 else if (strcmp(args[myidx], "type") == 0) {
2785 myidx++;
2786 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2787 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2788 file, linenum, args[myidx]);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002792 /* myidx already points to next arg */
2793 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002794 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002795 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002796 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002797
2798 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 nw = args[myidx];
2800 while (*nw) {
2801 /* the "store" keyword supports a comma-separated list */
2802 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002803 sa = NULL; /* store arg */
2804 while (*nw && *nw != ',') {
2805 if (*nw == '(') {
2806 *nw = 0;
2807 sa = ++nw;
2808 while (*nw != ')') {
2809 if (!*nw) {
2810 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2811 file, linenum, args[0], cw);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814 }
2815 nw++;
2816 }
2817 *nw = '\0';
2818 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002819 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002820 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002821 if (*nw)
2822 *nw++ = '\0';
2823 type = stktable_get_data_type(cw);
2824 if (type < 0) {
2825 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2826 file, linenum, args[0], cw);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
Willy Tarreauac782882010-06-20 10:41:54 +02002830
2831 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2832 switch (err) {
2833 case PE_NONE: break;
2834 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002835 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2836 file, linenum, args[0], cw);
2837 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002838 break;
2839
2840 case PE_ARG_MISSING:
2841 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2842 file, linenum, args[0], cw);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845
2846 case PE_ARG_NOT_USED:
2847 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2848 file, linenum, args[0], cw);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851
2852 default:
2853 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2854 file, linenum, args[0], cw);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002857 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002858 }
2859 myidx++;
2860 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002861 else {
2862 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2863 file, linenum, args[myidx]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002866 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
2868
2869 if (!curproxy->table.size) {
2870 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2871 file, linenum);
2872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
2874 }
2875
2876 if (curproxy->table.type == (unsigned int)-1) {
2877 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2878 file, linenum);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 }
2883 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002884 struct sticking_rule *rule;
2885 struct pattern_expr *expr;
2886 int myidx = 0;
2887 const char *name = NULL;
2888 int flags;
2889
2890 if (curproxy == &defproxy) {
2891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
2895
2896 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2897 err_code |= ERR_WARN;
2898 goto out;
2899 }
2900
2901 myidx++;
2902 if ((strcmp(args[myidx], "store") == 0) ||
2903 (strcmp(args[myidx], "store-request") == 0)) {
2904 myidx++;
2905 flags = STK_IS_STORE;
2906 }
2907 else if (strcmp(args[myidx], "store-response") == 0) {
2908 myidx++;
2909 flags = STK_IS_STORE | STK_ON_RSP;
2910 }
2911 else if (strcmp(args[myidx], "match") == 0) {
2912 myidx++;
2913 flags = STK_IS_MATCH;
2914 }
2915 else if (strcmp(args[myidx], "on") == 0) {
2916 myidx++;
2917 flags = STK_IS_MATCH | STK_IS_STORE;
2918 }
2919 else {
2920 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924
2925 if (*(args[myidx]) == 0) {
2926 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930
Emeric Brun485479d2010-09-23 18:02:19 +02002931 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002932 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002933 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
2936 }
2937
2938 if (flags & STK_ON_RSP) {
2939 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2940 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2941 file, linenum, args[0], expr->fetch->kw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945 } else {
2946 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2947 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2948 file, linenum, args[0], expr->fetch->kw);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 }
2953
2954 if (strcmp(args[myidx], "table") == 0) {
2955 myidx++;
2956 name = args[myidx++];
2957 }
2958
Willy Tarreauef6494c2010-01-28 17:12:36 +01002959 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2960 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2962 file, linenum, args[0]);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002966 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002967 else if (*(args[myidx])) {
2968 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2969 file, linenum, args[0], args[myidx]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
Emeric Brun97679e72010-09-23 17:56:44 +02002973 if (flags & STK_ON_RSP)
2974 err_code |= warnif_cond_requires_req(cond, file, linenum);
2975 else
2976 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002977
Emeric Brunb982a3d2010-01-04 15:45:53 +01002978 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2979 rule->cond = cond;
2980 rule->expr = expr;
2981 rule->flags = flags;
2982 rule->table.name = name ? strdup(name) : NULL;
2983 LIST_INIT(&rule->list);
2984 if (flags & STK_ON_RSP)
2985 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2986 else
2987 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2994 curproxy->uri_auth = NULL; /* we must detach from the default config */
2995
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002996 if (!*args[1]) {
2997 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002998 } else if (!strcmp(args[1], "admin")) {
2999 struct stats_admin_rule *rule;
3000
3001 if (curproxy == &defproxy) {
3002 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
3007 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3008 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3009 err_code |= ERR_ALERT | ERR_ABORT;
3010 goto out;
3011 }
3012
3013 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3014 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3015 file, linenum, args[0], args[1]);
3016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
3018 }
3019 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3020 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3021 file, linenum, args[0], args[1]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3027
3028 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3029 rule->cond = cond;
3030 LIST_INIT(&rule->list);
3031 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 } else if (!strcmp(args[1], "uri")) {
3033 if (*(args[2]) == 0) {
3034 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3038 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_ABORT;
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
3042 } else if (!strcmp(args[1], "realm")) {
3043 if (*(args[2]) == 0) {
3044 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_ABORT;
3050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003052 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003053 unsigned interval;
3054
3055 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3056 if (err) {
3057 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3058 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003061 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3062 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_ABORT;
3064 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003065 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003066 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3067 struct req_acl_rule *req_acl;
3068
3069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
3075 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3076 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3077 err_code |= ERR_ALERT | ERR_ABORT;
3078 goto out;
3079 }
3080
3081 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3082 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3083 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3084 file, linenum, args[0]);
3085 err_code |= ERR_WARN;
3086 }
3087
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003088 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003089
3090 if (!req_acl) {
3091 err_code |= ERR_ALERT | ERR_ABORT;
3092 goto out;
3093 }
3094
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003095 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003096 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3097
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 } else if (!strcmp(args[1], "auth")) {
3099 if (*(args[2]) == 0) {
3100 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3104 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_ABORT;
3106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 }
3108 } else if (!strcmp(args[1], "scope")) {
3109 if (*(args[2]) == 0) {
3110 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_ABORT;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
3118 } else if (!strcmp(args[1], "enable")) {
3119 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_ALERT | ERR_ABORT;
3122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003124 } else if (!strcmp(args[1], "hide-version")) {
3125 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_ABORT;
3128 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003129 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003130 } else if (!strcmp(args[1], "show-legends")) {
3131 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3132 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
3135 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003136 } else if (!strcmp(args[1], "show-node")) {
3137
3138 if (*args[2]) {
3139 int i;
3140 char c;
3141
3142 for (i=0; args[2][i]; i++) {
3143 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003144 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3145 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003146 break;
3147 }
3148
3149 if (!i || args[2][i]) {
3150 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3151 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3152 file, linenum, args[0], args[1]);
3153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
3155 }
3156 }
3157
3158 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3159 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3160 err_code |= ERR_ALERT | ERR_ABORT;
3161 goto out;
3162 }
3163 } else if (!strcmp(args[1], "show-desc")) {
3164 char *desc = NULL;
3165
3166 if (*args[2]) {
3167 int i, len=0;
3168 char *d;
3169
3170 for(i=2; *args[i]; i++)
3171 len += strlen(args[i])+1;
3172
3173 desc = d = (char *)calloc(1, len);
3174
3175 d += sprintf(d, "%s", args[2]);
3176 for(i=3; *args[i]; i++)
3177 d += sprintf(d, " %s", args[i]);
3178 }
3179
3180 if (!*args[2] && !global.desc)
3181 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3182 file, linenum, args[1]);
3183 else {
3184 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3185 free(desc);
3186 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3187 err_code |= ERR_ALERT | ERR_ABORT;
3188 goto out;
3189 }
3190 free(desc);
3191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003193stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003194 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 +01003195 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 }
3200 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003201 int optnum;
3202
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003203 if (*(args[1]) == '\0') {
3204 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003209
3210 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3211 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003212 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3213 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3214 file, linenum, cfg_opts[optnum].name);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
Willy Tarreau93893792009-07-23 13:19:11 +02003218 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3219 err_code |= ERR_WARN;
3220 goto out;
3221 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003222
Willy Tarreau3842f002009-06-14 11:39:52 +02003223 curproxy->no_options &= ~cfg_opts[optnum].val;
3224 curproxy->options &= ~cfg_opts[optnum].val;
3225
3226 switch (kwm) {
3227 case KWM_STD:
3228 curproxy->options |= cfg_opts[optnum].val;
3229 break;
3230 case KWM_NO:
3231 curproxy->no_options |= cfg_opts[optnum].val;
3232 break;
3233 case KWM_DEF: /* already cleared */
3234 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003235 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003236
Willy Tarreau93893792009-07-23 13:19:11 +02003237 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003238 }
3239 }
3240
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003241 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3242 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003243 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3244 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3245 file, linenum, cfg_opts2[optnum].name);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
Willy Tarreau93893792009-07-23 13:19:11 +02003249 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3250 err_code |= ERR_WARN;
3251 goto out;
3252 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003253
Willy Tarreau3842f002009-06-14 11:39:52 +02003254 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3255 curproxy->options2 &= ~cfg_opts2[optnum].val;
3256
3257 switch (kwm) {
3258 case KWM_STD:
3259 curproxy->options2 |= cfg_opts2[optnum].val;
3260 break;
3261 case KWM_NO:
3262 curproxy->no_options2 |= cfg_opts2[optnum].val;
3263 break;
3264 case KWM_DEF: /* already cleared */
3265 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003266 }
Willy Tarreau93893792009-07-23 13:19:11 +02003267 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003268 }
3269 }
3270
Willy Tarreau3842f002009-06-14 11:39:52 +02003271 if (kwm != KWM_STD) {
3272 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003273 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003276 }
3277
Emeric Brun3a058f32009-06-30 18:26:00 +02003278 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003280 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003282 if (*(args[2]) != '\0') {
3283 if (!strcmp(args[2], "clf")) {
3284 curproxy->options2 |= PR_O2_CLFLOG;
3285 } else {
3286 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003289 }
3290 }
3291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 else if (!strcmp(args[1], "tcplog"))
3293 /* generate a detailed TCP log */
3294 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 else if (!strcmp(args[1], "tcpka")) {
3296 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003297 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003299
3300 if (curproxy->cap & PR_CAP_FE)
3301 curproxy->options |= PR_O_TCP_CLI_KA;
3302 if (curproxy->cap & PR_CAP_BE)
3303 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
3305 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_WARN;
3308
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003310 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003311 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003312 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003313 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003314 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003315 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003316 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003317 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 if (!*args[2]) { /* no argument */
3319 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3320 curproxy->check_len = strlen(DEF_CHECK_REQ);
3321 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003322 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 curproxy->check_req = (char *)malloc(reqlen);
3324 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003325 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003327 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 if (*args[4])
3329 reqlen += strlen(args[4]);
3330 else
3331 reqlen += strlen("HTTP/1.0");
3332
3333 curproxy->check_req = (char *)malloc(reqlen);
3334 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003335 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003337 }
3338 else if (!strcmp(args[1], "ssl-hello-chk")) {
3339 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003340 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003342
Willy Tarreaua534fea2008-08-03 12:19:50 +02003343 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003344 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003345 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003346 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003347 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003348 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003349 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003350 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }
Willy Tarreau23677902007-05-08 23:50:35 +02003352 else if (!strcmp(args[1], "smtpchk")) {
3353 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003354 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003355 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003356 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003357 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003358 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003359 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003360 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003361 curproxy->options |= PR_O_SMTP_CHK;
3362
3363 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3364 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3365 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3366 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3367 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3368 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3369 curproxy->check_req = (char *)malloc(reqlen);
3370 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3371 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3372 } else {
3373 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3374 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3375 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3376 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3377 }
3378 }
3379 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003380 else if (!strcmp(args[1], "pgsql-check")) {
3381 /* use PostgreSQL request to check servers' health */
3382 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3383 err_code |= ERR_WARN;
3384
3385 free(curproxy->check_req);
3386 curproxy->check_req = NULL;
3387 curproxy->options &= ~PR_O_HTTP_CHK;
3388 curproxy->options &= ~PR_O_SMTP_CHK;
3389 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3390 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3391 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3392 curproxy->options2 |= PR_O2_PGSQL_CHK;
3393
3394 if (*(args[2])) {
3395 int cur_arg = 2;
3396
3397 while (*(args[cur_arg])) {
3398 if (strcmp(args[cur_arg], "user") == 0) {
3399 char * packet;
3400 uint32_t packet_len;
3401 uint32_t pv;
3402
3403 /* suboption header - needs additional argument for it */
3404 if (*(args[cur_arg+1]) == 0) {
3405 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3406 file, linenum, args[0], args[1], args[cur_arg]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
3410
3411 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3412 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3413 pv = htonl(0x30000); /* protocol version 3.0 */
3414
3415 packet = (char*) calloc(1, packet_len);
3416
3417 memcpy(packet + 4, &pv, 4);
3418
3419 /* copy "user" */
3420 memcpy(packet + 8, "user", 4);
3421
3422 /* copy username */
3423 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3424
3425 free(curproxy->check_req);
3426 curproxy->check_req = packet;
3427 curproxy->check_len = packet_len;
3428
3429 packet_len = htonl(packet_len);
3430 memcpy(packet, &packet_len, 4);
3431 cur_arg += 2;
3432 } else {
3433 /* unknown suboption - catchall */
3434 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3435 file, linenum, args[0], args[1]);
3436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
3438 }
3439 } /* end while loop */
3440 }
3441 }
3442
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003443 else if (!strcmp(args[1], "mysql-check")) {
3444 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3446 err_code |= ERR_WARN;
3447
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003448 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003449 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003450 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003451 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003452 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003453 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003454 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003455 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003456
3457 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3458 * const char mysql40_client_auth_pkt[] = {
3459 * "\x0e\x00\x00" // packet length
3460 * "\x01" // packet number
3461 * "\x00\x00" // client capabilities
3462 * "\x00\x00\x01" // max packet
3463 * "haproxy\x00" // username (null terminated string)
3464 * "\x00" // filler (always 0x00)
3465 * "\x01\x00\x00" // packet length
3466 * "\x00" // packet number
3467 * "\x01" // COM_QUIT command
3468 * };
3469 */
3470
3471 if (*(args[2])) {
3472 int cur_arg = 2;
3473
3474 while (*(args[cur_arg])) {
3475 if (strcmp(args[cur_arg], "user") == 0) {
3476 char *mysqluser;
3477 int packetlen, reqlen, userlen;
3478
3479 /* suboption header - needs additional argument for it */
3480 if (*(args[cur_arg+1]) == 0) {
3481 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3482 file, linenum, args[0], args[1], args[cur_arg]);
3483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
3485 }
3486 mysqluser = args[cur_arg + 1];
3487 userlen = strlen(mysqluser);
3488 packetlen = userlen + 7;
3489 reqlen = packetlen + 9;
3490
3491 free(curproxy->check_req);
3492 curproxy->check_req = (char *)calloc(1, reqlen);
3493 curproxy->check_len = reqlen;
3494
3495 snprintf(curproxy->check_req, 4, "%c%c%c",
3496 ((unsigned char) packetlen & 0xff),
3497 ((unsigned char) (packetlen >> 8) & 0xff),
3498 ((unsigned char) (packetlen >> 16) & 0xff));
3499
3500 curproxy->check_req[3] = 1;
3501 curproxy->check_req[8] = 1;
3502 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3503 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3504 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3505 cur_arg += 2;
3506 } else {
3507 /* unknown suboption - catchall */
3508 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3509 file, linenum, args[0], args[1]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513 } /* end while loop */
3514 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003515 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003516 else if (!strcmp(args[1], "ldap-check")) {
3517 /* use LDAP request to check servers' health */
3518 free(curproxy->check_req);
3519 curproxy->check_req = NULL;
3520 curproxy->options &= ~PR_O_HTTP_CHK;
3521 curproxy->options &= ~PR_O_SMTP_CHK;
3522 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3523 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003524 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003525 curproxy->options2 |= PR_O2_LDAP_CHK;
3526
3527 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3528 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3529 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3530 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003531 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003532 int cur_arg;
3533
3534 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3535 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003536 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003537
3538 curproxy->options |= PR_O_FWDFOR;
3539
3540 free(curproxy->fwdfor_hdr_name);
3541 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3542 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3543
3544 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3545 cur_arg = 2;
3546 while (*(args[cur_arg])) {
3547 if (!strcmp(args[cur_arg], "except")) {
3548 /* suboption except - needs additional argument for it */
3549 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3550 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3551 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003554 }
3555 /* flush useless bits */
3556 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003557 cur_arg += 2;
3558 } else if (!strcmp(args[cur_arg], "header")) {
3559 /* suboption header - needs additional argument for it */
3560 if (*(args[cur_arg+1]) == 0) {
3561 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3562 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003565 }
3566 free(curproxy->fwdfor_hdr_name);
3567 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3568 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3569 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003570 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003571 /* unknown suboption - catchall */
3572 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3573 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003576 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003577 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003578 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003579 else if (!strcmp(args[1], "originalto")) {
3580 int cur_arg;
3581
3582 /* insert x-original-to field, but not for the IP address listed as an except.
3583 * set default options (ie: bitfield, header name, etc)
3584 */
3585
3586 curproxy->options |= PR_O_ORGTO;
3587
3588 free(curproxy->orgto_hdr_name);
3589 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3590 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3591
3592 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3593 cur_arg = 2;
3594 while (*(args[cur_arg])) {
3595 if (!strcmp(args[cur_arg], "except")) {
3596 /* suboption except - needs additional argument for it */
3597 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3598 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3599 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003602 }
3603 /* flush useless bits */
3604 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3605 cur_arg += 2;
3606 } else if (!strcmp(args[cur_arg], "header")) {
3607 /* suboption header - needs additional argument for it */
3608 if (*(args[cur_arg+1]) == 0) {
3609 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3610 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003613 }
3614 free(curproxy->orgto_hdr_name);
3615 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3616 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3617 cur_arg += 2;
3618 } else {
3619 /* unknown suboption - catchall */
3620 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3621 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003624 }
3625 } /* end while loop */
3626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 else {
3628 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 }
Willy Tarreau93893792009-07-23 13:19:11 +02003632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003634 else if (!strcmp(args[0], "default_backend")) {
3635 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003637
3638 if (*(args[1]) == 0) {
3639 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003642 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003643 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003644 curproxy->defbe.name = strdup(args[1]);
3645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003647 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003649
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003650 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 /* enable reconnections to dispatch */
3654 curproxy->options |= PR_O_REDISP;
3655 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003656 else if (!strcmp(args[0], "http-check")) {
3657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003659
3660 if (strcmp(args[1], "disable-on-404") == 0) {
3661 /* enable a graceful server shutdown on an HTTP 404 response */
3662 curproxy->options |= PR_O_DISABLE404;
3663 }
Willy Tarreauef781042010-01-27 11:53:01 +01003664 else if (strcmp(args[1], "send-state") == 0) {
3665 /* enable emission of the apparent state of a server in HTTP checks */
3666 curproxy->options2 |= PR_O2_CHK_SNDST;
3667 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003668 else if (strcmp(args[1], "expect") == 0) {
3669 const char *ptr_arg;
3670 int cur_arg;
3671
3672 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3673 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
3676 }
3677
3678 cur_arg = 2;
3679 /* consider exclamation marks, sole or at the beginning of a word */
3680 while (*(ptr_arg = args[cur_arg])) {
3681 while (*ptr_arg == '!') {
3682 curproxy->options2 ^= PR_O2_EXP_INV;
3683 ptr_arg++;
3684 }
3685 if (*ptr_arg)
3686 break;
3687 cur_arg++;
3688 }
3689 /* now ptr_arg points to the beginning of a word past any possible
3690 * exclamation mark, and cur_arg is the argument which holds this word.
3691 */
3692 if (strcmp(ptr_arg, "status") == 0) {
3693 if (!*(args[cur_arg + 1])) {
3694 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3695 file, linenum, args[0], args[1], ptr_arg);
3696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
3698 }
3699 curproxy->options2 |= PR_O2_EXP_STS;
3700 curproxy->expect_str = strdup(args[cur_arg + 1]);
3701 }
3702 else if (strcmp(ptr_arg, "string") == 0) {
3703 if (!*(args[cur_arg + 1])) {
3704 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3705 file, linenum, args[0], args[1], ptr_arg);
3706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
3708 }
3709 curproxy->options2 |= PR_O2_EXP_STR;
3710 curproxy->expect_str = strdup(args[cur_arg + 1]);
3711 }
3712 else if (strcmp(ptr_arg, "rstatus") == 0) {
3713 if (!*(args[cur_arg + 1])) {
3714 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3715 file, linenum, args[0], args[1], ptr_arg);
3716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
3718 }
3719 curproxy->options2 |= PR_O2_EXP_RSTS;
3720 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3721 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3722 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3723 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727 }
3728 else if (strcmp(ptr_arg, "rstring") == 0) {
3729 if (!*(args[cur_arg + 1])) {
3730 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3731 file, linenum, args[0], args[1], ptr_arg);
3732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
3734 }
3735 curproxy->options2 |= PR_O2_EXP_RSTR;
3736 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3737 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3738 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3739 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743 }
3744 else {
3745 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3746 file, linenum, args[0], args[1], ptr_arg);
3747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
3749 }
3750 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003751 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003752 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003755 }
3756 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003757 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003758 if (curproxy == &defproxy) {
3759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003762 }
3763
Willy Tarreaub80c2302007-11-30 20:51:32 +01003764 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003766
3767 if (strcmp(args[1], "fail") == 0) {
3768 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003769 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003770 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3771 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003774 }
3775
Willy Tarreauef6494c2010-01-28 17:12:36 +01003776 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003777 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3778 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003781 }
3782 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3783 }
3784 else {
3785 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003788 }
3789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790#ifdef TPROXY
3791 else if (!strcmp(args[0], "transparent")) {
3792 /* enable transparent proxy connections */
3793 curproxy->options |= PR_O_TRANSP;
3794 }
3795#endif
3796 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003797 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003799
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 if (*(args[1]) == 0) {
3801 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 }
3805 curproxy->maxconn = atol(args[1]);
3806 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003807 else if (!strcmp(args[0], "backlog")) { /* backlog */
3808 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003810
3811 if (*(args[1]) == 0) {
3812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003815 }
3816 curproxy->backlog = atol(args[1]);
3817 }
Willy Tarreau86034312006-12-29 00:10:33 +01003818 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003819 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003821
Willy Tarreau86034312006-12-29 00:10:33 +01003822 if (*(args[1]) == 0) {
3823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003826 }
3827 curproxy->fullconn = atol(args[1]);
3828 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3830 if (*(args[1]) == 0) {
3831 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003835 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3836 if (err) {
3837 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3838 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003841 }
3842 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 }
3844 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003845 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 if (curproxy == &defproxy) {
3847 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003851 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003853
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 if (strchr(args[1], ':') == NULL) {
3855 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003859 sk = str2sa(args[1]);
3860 if (!sk) {
3861 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
3865 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
3867 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003868 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003869 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003870
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003871 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003872 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3873 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003878 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3879 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3880 err_code |= ERR_WARN;
3881
3882 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3883 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3884 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3885 }
3886 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3887 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3888 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3889 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003890 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3891 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3892 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3893 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003894 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003895 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
3898 }
3899 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003900 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003902 char *rport, *raddr;
3903 short realport = 0;
3904 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003906 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003910 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003911 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003913
3914 if (!*args[2]) {
3915 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003920
3921 err = invalid_char(args[1]);
3922 if (err) {
3923 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3924 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003927 }
3928
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003929 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003930 struct sockaddr_in *sk;
3931
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003932 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3933 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3934 err_code |= ERR_ALERT | ERR_ABORT;
3935 goto out;
3936 }
3937
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003938 /* the servers are linked backwards first */
3939 newsrv->next = curproxy->srv;
3940 curproxy->srv = newsrv;
3941 newsrv->proxy = curproxy;
3942 newsrv->conf.file = file;
3943 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003945 LIST_INIT(&newsrv->pendconns);
3946 do_check = 0;
3947 newsrv->state = SRV_RUNNING; /* early server setup */
3948 newsrv->last_change = now.tv_sec;
3949 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003951 /* several ways to check the port component :
3952 * - IP => port=+0, relative
3953 * - IP: => port=+0, relative
3954 * - IP:N => port=N, absolute
3955 * - IP:+N => port=+N, relative
3956 * - IP:-N => port=-N, relative
3957 */
3958 raddr = strdup(args[2]);
3959 rport = strchr(raddr, ':');
3960 if (rport) {
3961 *rport++ = 0;
3962 realport = atol(rport);
3963 if (!isdigit((unsigned char)*rport))
3964 newsrv->state |= SRV_MAPPORTS;
3965 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003966 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003967
Willy Tarreaud5191e72010-02-09 20:50:45 +01003968 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003969 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003970 if (!sk) {
3971 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975 newsrv->addr = *sk;
3976 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003977
3978 newsrv->check_port = curproxy->defsrv.check_port;
3979 newsrv->inter = curproxy->defsrv.inter;
3980 newsrv->fastinter = curproxy->defsrv.fastinter;
3981 newsrv->downinter = curproxy->defsrv.downinter;
3982 newsrv->rise = curproxy->defsrv.rise;
3983 newsrv->fall = curproxy->defsrv.fall;
3984 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3985 newsrv->minconn = curproxy->defsrv.minconn;
3986 newsrv->maxconn = curproxy->defsrv.maxconn;
3987 newsrv->slowstart = curproxy->defsrv.slowstart;
3988 newsrv->onerror = curproxy->defsrv.onerror;
3989 newsrv->consecutive_errors_limit
3990 = curproxy->defsrv.consecutive_errors_limit;
3991 newsrv->uweight = newsrv->iweight
3992 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003994 newsrv->curfd = -1; /* no health-check in progress */
3995 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003997 cur_arg = 3;
3998 } else {
3999 newsrv = &curproxy->defsrv;
4000 cur_arg = 1;
4001 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004002
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004004 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004005 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004006
4007 if (!*args[cur_arg + 1]) {
4008 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4009 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004012 }
4013
4014 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004015 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004016
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004017 if (newsrv->puid <= 0) {
4018 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004019 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004022 }
4023
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004024 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4025 if (node) {
4026 struct server *target = container_of(node, struct server, conf.id);
4027 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4028 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
4031 }
4032 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004033 cur_arg += 2;
4034 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004035 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 newsrv->cookie = strdup(args[cur_arg + 1]);
4037 newsrv->cklen = strlen(args[cur_arg + 1]);
4038 cur_arg += 2;
4039 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004040 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004041 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4042 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4043 cur_arg += 2;
4044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004046 if (!*args[cur_arg + 1]) {
4047 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4048 file, linenum, args[cur_arg]);
4049 err_code |= ERR_ALERT | ERR_FATAL;
4050 goto out;
4051 }
4052
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004054 if (newsrv->rise <= 0) {
4055 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4056 file, linenum, args[cur_arg]);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
4060
Willy Tarreau96839092010-03-29 10:02:24 +02004061 if (newsrv->health)
4062 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 cur_arg += 2;
4064 }
4065 else if (!strcmp(args[cur_arg], "fall")) {
4066 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004067
4068 if (!*args[cur_arg + 1]) {
4069 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4070 file, linenum, args[cur_arg]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074
4075 if (newsrv->fall <= 0) {
4076 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4077 file, linenum, args[cur_arg]);
4078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
4080 }
4081
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 cur_arg += 2;
4083 }
4084 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004085 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4086 if (err) {
4087 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4088 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004091 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004092 if (val <= 0) {
4093 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4094 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004097 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004098 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 cur_arg += 2;
4100 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004101 else if (!strcmp(args[cur_arg], "fastinter")) {
4102 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4103 if (err) {
4104 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4105 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004108 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004109 if (val <= 0) {
4110 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4111 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004114 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004115 newsrv->fastinter = val;
4116 cur_arg += 2;
4117 }
4118 else if (!strcmp(args[cur_arg], "downinter")) {
4119 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4120 if (err) {
4121 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4122 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004125 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004126 if (val <= 0) {
4127 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4128 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004131 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004132 newsrv->downinter = val;
4133 cur_arg += 2;
4134 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004135 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004136 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4137 if (!sk) {
4138 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
4141 }
4142 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004143 cur_arg += 2;
4144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145 else if (!strcmp(args[cur_arg], "port")) {
4146 newsrv->check_port = atol(args[cur_arg + 1]);
4147 cur_arg += 2;
4148 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004149 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 newsrv->state |= SRV_BACKUP;
4151 cur_arg ++;
4152 }
4153 else if (!strcmp(args[cur_arg], "weight")) {
4154 int w;
4155 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004156 if (w < 0 || w > 256) {
4157 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004162 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 cur_arg += 2;
4164 }
4165 else if (!strcmp(args[cur_arg], "minconn")) {
4166 newsrv->minconn = atol(args[cur_arg + 1]);
4167 cur_arg += 2;
4168 }
4169 else if (!strcmp(args[cur_arg], "maxconn")) {
4170 newsrv->maxconn = atol(args[cur_arg + 1]);
4171 cur_arg += 2;
4172 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004173 else if (!strcmp(args[cur_arg], "maxqueue")) {
4174 newsrv->maxqueue = atol(args[cur_arg + 1]);
4175 cur_arg += 2;
4176 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004177 else if (!strcmp(args[cur_arg], "slowstart")) {
4178 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004179 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004180 if (err) {
4181 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4182 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004185 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004186 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004187 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4188 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004191 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004192 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004193 cur_arg += 2;
4194 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004195 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004196
4197 if (!*args[cur_arg + 1]) {
4198 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4199 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004202 }
4203
4204 newsrv->trackit = strdup(args[cur_arg + 1]);
4205
4206 cur_arg += 2;
4207 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004208 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 global.maxsock++;
4210 do_check = 1;
4211 cur_arg += 1;
4212 }
Willy Tarreau96839092010-03-29 10:02:24 +02004213 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4214 newsrv->state |= SRV_MAINTAIN;
4215 newsrv->state &= ~SRV_RUNNING;
4216 newsrv->health = 0;
4217 cur_arg += 1;
4218 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004219 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004220 if (!strcmp(args[cur_arg + 1], "none"))
4221 newsrv->observe = HANA_OBS_NONE;
4222 else if (!strcmp(args[cur_arg + 1], "layer4"))
4223 newsrv->observe = HANA_OBS_LAYER4;
4224 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4225 if (curproxy->mode != PR_MODE_HTTP) {
4226 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4227 file, linenum, args[cur_arg + 1]);
4228 err_code |= ERR_ALERT;
4229 }
4230 newsrv->observe = HANA_OBS_LAYER7;
4231 }
4232 else {
4233 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004234 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004235 file, linenum, args[cur_arg], args[cur_arg + 1]);
4236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
4238 }
4239
4240 cur_arg += 2;
4241 }
4242 else if (!strcmp(args[cur_arg], "on-error")) {
4243 if (!strcmp(args[cur_arg + 1], "fastinter"))
4244 newsrv->onerror = HANA_ONERR_FASTINTER;
4245 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4246 newsrv->onerror = HANA_ONERR_FAILCHK;
4247 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4248 newsrv->onerror = HANA_ONERR_SUDDTH;
4249 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4250 newsrv->onerror = HANA_ONERR_MARKDWN;
4251 else {
4252 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004253 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004254 file, linenum, args[cur_arg], args[cur_arg + 1]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
4259 cur_arg += 2;
4260 }
4261 else if (!strcmp(args[cur_arg], "error-limit")) {
4262 if (!*args[cur_arg + 1]) {
4263 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4264 file, linenum, args[cur_arg]);
4265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
4268
4269 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4270
4271 if (newsrv->consecutive_errors_limit <= 0) {
4272 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4273 file, linenum, args[cur_arg]);
4274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
4276 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004277 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004278 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004279 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004280 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004281 struct sockaddr_in *sk;
4282
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004284#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004285 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004286 file, linenum, "source", "usesrc");
4287#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004288 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004290#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 }
4294 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004295 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4296 if (!sk) {
4297 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
4301 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004302
4303 if (port_low != port_high) {
4304 int i;
4305 if (port_low <= 0 || port_low > 65535 ||
4306 port_high <= 0 || port_high > 65535 ||
4307 port_low > port_high) {
4308 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4309 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004312 }
4313 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4314 for (i = 0; i < newsrv->sport_range->size; i++)
4315 newsrv->sport_range->ports[i] = port_low + i;
4316 }
4317
Willy Tarreaubaaee002006-06-26 02:48:02 +02004318 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004319 while (*(args[cur_arg])) {
4320 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004321#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4322#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004323 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4324 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4325 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004329#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004330 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004331 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004332 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004335 }
4336 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004337 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004338 newsrv->state |= SRV_TPROXY_CLI;
4339 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004340 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004341 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004342 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4343 char *name, *end;
4344
4345 name = args[cur_arg+1] + 7;
4346 while (isspace(*name))
4347 name++;
4348
4349 end = name;
4350 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4351 end++;
4352
4353 newsrv->state &= ~SRV_TPROXY_MASK;
4354 newsrv->state |= SRV_TPROXY_DYN;
4355 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4356 newsrv->bind_hdr_len = end - name;
4357 memcpy(newsrv->bind_hdr_name, name, end - name);
4358 newsrv->bind_hdr_name[end-name] = '\0';
4359 newsrv->bind_hdr_occ = -1;
4360
4361 /* now look for an occurrence number */
4362 while (isspace(*end))
4363 end++;
4364 if (*end == ',') {
4365 end++;
4366 name = end;
4367 if (*end == '-')
4368 end++;
4369 while (isdigit(*end))
4370 end++;
4371 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4372 }
4373
4374 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4375 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4376 " occurrences values smaller than %d.\n",
4377 file, linenum, MAX_HDR_HISTORY);
4378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
4380 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004381 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004382 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4383 if (!sk) {
4384 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
4387 }
4388 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004389 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004390 }
4391 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004392#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004393 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004394#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395 cur_arg += 2;
4396 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004397#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004398 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004399 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004402#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4403 } /* "usesrc" */
4404
4405 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4406#ifdef SO_BINDTODEVICE
4407 if (!*args[cur_arg + 1]) {
4408 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4409 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004412 }
4413 if (newsrv->iface_name)
4414 free(newsrv->iface_name);
4415
4416 newsrv->iface_name = strdup(args[cur_arg + 1]);
4417 newsrv->iface_len = strlen(newsrv->iface_name);
4418 global.last_checks |= LSTCHK_NETADM;
4419#else
4420 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4421 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004424#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004425 cur_arg += 2;
4426 continue;
4427 }
4428 /* this keyword in not an option of "source" */
4429 break;
4430 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004432 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004433 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4434 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004439 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004440 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 +01004441 file, linenum, newsrv->id);
4442 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004443 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 +01004444 file, linenum);
4445
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
4449 }
4450
4451 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004452 if (newsrv->trackit) {
4453 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4454 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004457 }
4458
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004459 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4460 newsrv->check_port = newsrv->check_addr.sin_port;
4461
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4463 newsrv->check_port = realport; /* by default */
4464 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004465 /* not yet valid, because no port was set on
4466 * the server either. We'll check if we have
4467 * a known port on the first listener.
4468 */
4469 struct listener *l;
4470 l = curproxy->listen;
4471 if (l) {
4472 int port;
4473 port = (l->addr.ss_family == AF_INET6)
4474 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4475 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4476 newsrv->check_port = port;
4477 }
4478 }
4479 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4481 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004485
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004486 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004487 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004488 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4489 err_code |= ERR_ALERT | ERR_ABORT;
4490 goto out;
4491 }
4492
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004493 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 newsrv->state |= SRV_CHECKED;
4495 }
4496
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004497 if (!defsrv) {
4498 if (newsrv->state & SRV_BACKUP)
4499 curproxy->srv_bck++;
4500 else
4501 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004502
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004503 newsrv->prev_state = newsrv->state;
4504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
4506 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004507 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 int facility;
4509
4510 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4511 curproxy->logfac1 = global.logfac1;
4512 curproxy->logsrv1 = global.logsrv1;
4513 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004514 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 curproxy->logfac2 = global.logfac2;
4516 curproxy->logsrv2 = global.logsrv2;
4517 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004518 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 }
4520 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004521 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522
4523 facility = get_log_facility(args[2]);
4524 if (facility < 0) {
4525 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4526 exit(1);
4527 }
4528
4529 level = 7; /* max syslog level = debug */
4530 if (*(args[3])) {
4531 level = get_log_level(args[3]);
4532 if (level < 0) {
4533 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4534 exit(1);
4535 }
4536 }
4537
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004538 minlvl = 0; /* limit syslog level to this level (emerg) */
4539 if (*(args[4])) {
4540 minlvl = get_log_level(args[4]);
4541 if (level < 0) {
4542 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4543 exit(1);
4544 }
4545 }
4546
Robert Tsai81ae1952007-12-05 10:47:29 +01004547 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004548 struct sockaddr_un *sk = str2sun(args[1]);
4549 if (!sk) {
4550 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4551 args[1], (int)sizeof(sk->sun_path) - 1);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004556 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004557 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004558 struct sockaddr_in *sk = str2sa(args[1]);
4559 if (!sk) {
4560 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
4563 }
4564 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004565 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004566 if (!logsrv.u.in.sin_port) {
4567 logsrv.u.in.sin_port =
4568 htons(SYSLOG_PORT);
4569 }
4570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571
4572 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004573 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 curproxy->logfac1 = facility;
4575 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004576 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004577 }
4578 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004579 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 curproxy->logfac2 = facility;
4581 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004582 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
4584 else {
4585 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004588 }
4589 }
4590 else {
4591 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596 }
4597 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004598 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004599 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004600
Willy Tarreau977b8e42006-12-29 14:19:17 +01004601 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004603
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004605 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4606 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004610
4611 /* we must first clear any optional default setting */
4612 curproxy->options &= ~PR_O_TPXY_MASK;
4613 free(curproxy->iface_name);
4614 curproxy->iface_name = NULL;
4615 curproxy->iface_len = 0;
4616
Willy Tarreaud5191e72010-02-09 20:50:45 +01004617 sk = str2sa(args[1]);
4618 if (!sk) {
4619 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
4622 }
4623 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004625
4626 cur_arg = 2;
4627 while (*(args[cur_arg])) {
4628 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004629#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4630#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4632 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4633 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004636 }
4637#endif
4638 if (!*args[cur_arg + 1]) {
4639 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4640 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004643 }
4644
4645 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004646 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004647 curproxy->options |= PR_O_TPXY_CLI;
4648 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004649 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004650 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004651 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4652 char *name, *end;
4653
4654 name = args[cur_arg+1] + 7;
4655 while (isspace(*name))
4656 name++;
4657
4658 end = name;
4659 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4660 end++;
4661
4662 curproxy->options &= ~PR_O_TPXY_MASK;
4663 curproxy->options |= PR_O_TPXY_DYN;
4664 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4665 curproxy->bind_hdr_len = end - name;
4666 memcpy(curproxy->bind_hdr_name, name, end - name);
4667 curproxy->bind_hdr_name[end-name] = '\0';
4668 curproxy->bind_hdr_occ = -1;
4669
4670 /* now look for an occurrence number */
4671 while (isspace(*end))
4672 end++;
4673 if (*end == ',') {
4674 end++;
4675 name = end;
4676 if (*end == '-')
4677 end++;
4678 while (isdigit(*end))
4679 end++;
4680 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4681 }
4682
4683 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4684 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4685 " occurrences values smaller than %d.\n",
4686 file, linenum, MAX_HDR_HISTORY);
4687 err_code |= ERR_ALERT | ERR_FATAL;
4688 goto out;
4689 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004690 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004691 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4692 if (!sk) {
4693 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696 }
4697 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004698 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699 }
4700 global.last_checks |= LSTCHK_NETADM;
4701#if !defined(CONFIG_HAP_LINUX_TPROXY)
4702 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004703#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004704#else /* no TPROXY support */
4705 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004706 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004709#endif
4710 cur_arg += 2;
4711 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004712 }
4713
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004714 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4715#ifdef SO_BINDTODEVICE
4716 if (!*args[cur_arg + 1]) {
4717 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004721 }
4722 if (curproxy->iface_name)
4723 free(curproxy->iface_name);
4724
4725 curproxy->iface_name = strdup(args[cur_arg + 1]);
4726 curproxy->iface_len = strlen(curproxy->iface_name);
4727 global.last_checks |= LSTCHK_NETADM;
4728#else
4729 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4730 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004733#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004734 cur_arg += 2;
4735 continue;
4736 }
4737 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4738 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004743 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4744 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4745 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004750 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4752 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004756
4757 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4758 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004759 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004760 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
4763 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004764 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4765 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004766 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 }
4770 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004771 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4772 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004773 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 }
4777 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004778 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4779 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004780 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 }
4784 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004785 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4786 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004787 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004788 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004791 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004792 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4793 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004794 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004795 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004796 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004797 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004798 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004799 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4800 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004801 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004803 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004804 }
4805 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004806 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4807 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004808 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004810 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4815 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004816 err_code |= ERR_ALERT | ERR_FATAL;
4817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004818 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819
4820 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4821 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004822 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 }
4826 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004827 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4828 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004829 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 }
4833 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004834 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4835 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004836 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 }
4840 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004841 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4842 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004843 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
4847 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004848 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4849 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004850 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004851 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004854 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004855 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4856 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004857 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004858 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004859 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004862 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004863
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 if (curproxy == &defproxy) {
4865 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004869 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 if (*(args[1]) == 0) {
4873 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004876 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004877
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004878 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4879 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4880 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4881 file, linenum, args[0]);
4882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
4884 }
4885 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4886 }
4887 else if (*args[2]) {
4888 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4889 file, linenum, args[0], args[2]);
4890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
4892 }
4893
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004894 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004895 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004896 wl->s = strdup(args[1]);
4897 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004898 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 }
4900 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4903 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004907
Willy Tarreauade5ec42010-01-28 19:33:49 +01004908 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4909 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004910 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4916 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004917 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4923 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004924 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
4928 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004932 err_code |= ERR_ALERT | ERR_FATAL;
4933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
4935
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4937 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004938 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
4942 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4944 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004945 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 }
4949 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4951 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004952 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
4956 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004957 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004958
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 if (curproxy == &defproxy) {
4960 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004964 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 if (*(args[1]) == 0) {
4968 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 }
4972
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004973 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4974 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4975 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4976 file, linenum, args[0]);
4977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
4979 }
4980 err_code |= warnif_cond_requires_req(cond, file, linenum);
4981 }
4982 else if (*args[2]) {
4983 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4984 file, linenum, args[0], args[2]);
4985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004989 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004990 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004991 wl->s = strdup(args[1]);
4992 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 else if (!strcmp(args[0], "errorloc") ||
4995 !strcmp(args[0], "errorloc302") ||
4996 !strcmp(args[0], "errorloc303")) { /* error location */
4997 int errnum, errlen;
4998 char *err;
4999
Willy Tarreau977b8e42006-12-29 14:19:17 +01005000 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005002
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005004 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 }
5008
5009 errnum = atol(args[1]);
5010 if (!strcmp(args[0], "errorloc303")) {
5011 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5012 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5013 } else {
5014 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5015 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5016 }
5017
Willy Tarreau0f772532006-12-23 20:51:41 +01005018 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5019 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005020 chunk_destroy(&curproxy->errmsg[rc]);
5021 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005022 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005025
5026 if (rc >= HTTP_ERR_SIZE) {
5027 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5028 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 free(err);
5030 }
5031 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005032 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5033 int errnum, errlen, fd;
5034 char *err;
5035 struct stat stat;
5036
5037 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005039
5040 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005041 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005044 }
5045
5046 fd = open(args[2], O_RDONLY);
5047 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5048 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5049 file, linenum, args[2], args[1]);
5050 if (fd >= 0)
5051 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005054 }
5055
Willy Tarreau27a674e2009-08-17 07:23:33 +02005056 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005057 errlen = stat.st_size;
5058 } else {
5059 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005060 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005062 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005063 }
5064
5065 err = malloc(errlen); /* malloc() must succeed during parsing */
5066 errnum = read(fd, err, errlen);
5067 if (errnum != errlen) {
5068 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5069 file, linenum, args[2], args[1]);
5070 close(fd);
5071 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005074 }
5075 close(fd);
5076
5077 errnum = atol(args[1]);
5078 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5079 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005080 chunk_destroy(&curproxy->errmsg[rc]);
5081 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005082 break;
5083 }
5084 }
5085
5086 if (rc >= HTTP_ERR_SIZE) {
5087 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5088 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005090 free(err);
5091 }
5092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005094 struct cfg_kw_list *kwl;
5095 int index;
5096
5097 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5098 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5099 if (kwl->kw[index].section != CFG_LISTEN)
5100 continue;
5101 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5102 /* prepare error message just in case */
5103 snprintf(trash, sizeof(trash),
5104 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005105 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5106 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005107 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005110 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005111 else if (rc > 0) {
5112 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_WARN;
5114 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005115 }
Willy Tarreau93893792009-07-23 13:19:11 +02005116 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005117 }
5118 }
5119 }
5120
Willy Tarreau6daf3432008-01-22 16:44:08 +01005121 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 }
Willy Tarreau93893792009-07-23 13:19:11 +02005125 out:
5126 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127}
5128
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005129int
5130cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5131{
5132
5133 int err_code = 0;
5134 const char *err;
5135
5136 if (!strcmp(args[0], "userlist")) { /* new userlist */
5137 struct userlist *newul;
5138
5139 if (!*args[1]) {
5140 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5141 file, linenum, args[0]);
5142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
5144 }
5145
5146 err = invalid_char(args[1]);
5147 if (err) {
5148 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5149 file, linenum, *err, args[0], args[1]);
5150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
5152 }
5153
5154 for (newul = userlist; newul; newul = newul->next)
5155 if (!strcmp(newul->name, args[1])) {
5156 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5157 file, linenum, args[1]);
5158 err_code |= ERR_WARN;
5159 goto out;
5160 }
5161
5162 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5163 if (!newul) {
5164 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5165 err_code |= ERR_ALERT | ERR_ABORT;
5166 goto out;
5167 }
5168
5169 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5170 newul->name = strdup(args[1]);
5171
5172 if (!newul->groupusers | !newul->name) {
5173 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5174 err_code |= ERR_ALERT | ERR_ABORT;
5175 goto out;
5176 }
5177
5178 newul->next = userlist;
5179 userlist = newul;
5180
5181 } else if (!strcmp(args[0], "group")) { /* new group */
5182 int cur_arg, i;
5183 const char *err;
5184
5185 if (!*args[1]) {
5186 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5187 file, linenum, args[0]);
5188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
5190 }
5191
5192 err = invalid_char(args[1]);
5193 if (err) {
5194 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5195 file, linenum, *err, args[0], args[1]);
5196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
5198 }
5199
5200 for(i = 0; i < userlist->grpcnt; i++)
5201 if (!strcmp(userlist->groups[i], args[1])) {
5202 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5203 file, linenum, args[1], userlist->name);
5204 err_code |= ERR_ALERT;
5205 goto out;
5206 }
5207
5208 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5209 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5210 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214
5215 cur_arg = 2;
5216
5217 while (*args[cur_arg]) {
5218 if (!strcmp(args[cur_arg], "users")) {
5219 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5220 cur_arg += 2;
5221 continue;
5222 } else {
5223 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5224 file, linenum, args[0]);
5225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
5227 }
5228 }
5229
5230 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5231 } else if (!strcmp(args[0], "user")) { /* new user */
5232 struct auth_users *newuser;
5233 int cur_arg;
5234
5235 if (!*args[1]) {
5236 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5237 file, linenum, args[0]);
5238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
5240 }
5241
5242 for (newuser = userlist->users; newuser; newuser = newuser->next)
5243 if (!strcmp(newuser->user, args[1])) {
5244 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5245 file, linenum, args[1], userlist->name);
5246 err_code |= ERR_ALERT;
5247 goto out;
5248 }
5249
5250 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5251 if (!newuser) {
5252 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5253 err_code |= ERR_ALERT | ERR_ABORT;
5254 goto out;
5255 }
5256
5257 newuser->user = strdup(args[1]);
5258
5259 newuser->next = userlist->users;
5260 userlist->users = newuser;
5261
5262 cur_arg = 2;
5263
5264 while (*args[cur_arg]) {
5265 if (!strcmp(args[cur_arg], "password")) {
5266#ifndef CONFIG_HAP_CRYPT
5267 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5268 file, linenum);
5269 err_code |= ERR_ALERT;
5270#endif
5271 newuser->pass = strdup(args[cur_arg + 1]);
5272 cur_arg += 2;
5273 continue;
5274 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5275 newuser->pass = strdup(args[cur_arg + 1]);
5276 newuser->flags |= AU_O_INSECURE;
5277 cur_arg += 2;
5278 continue;
5279 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005280 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005281 cur_arg += 2;
5282 continue;
5283 } else {
5284 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5285 file, linenum, args[0]);
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
5289 }
5290 } else {
5291 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5292 err_code |= ERR_ALERT | ERR_FATAL;
5293 }
5294
5295out:
5296 return err_code;
5297}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298
5299/*
5300 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005301 * Returns the error code, 0 if OK, or any combination of :
5302 * - ERR_ABORT: must abort ASAP
5303 * - ERR_FATAL: we can continue parsing but not start the service
5304 * - ERR_WARN: a warning has been emitted
5305 * - ERR_ALERT: an alert has been emitted
5306 * Only the two first ones can stop processing, the two others are just
5307 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005309int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005311 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 FILE *f;
5313 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005315 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 if ((f=fopen(file,"r")) == NULL)
5318 return -1;
5319
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005320 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005321 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005322 char *end;
5323 char *args[MAX_LINE_ARGS + 1];
5324 char *line = thisline;
5325
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 linenum++;
5327
5328 end = line + strlen(line);
5329
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005330 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5331 /* Check if we reached the limit and the last char is not \n.
5332 * Watch out for the last line without the terminating '\n'!
5333 */
5334 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005335 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005336 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005337 }
5338
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005340 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 line++;
5342
5343 arg = 0;
5344 args[arg] = line;
5345
5346 while (*line && arg < MAX_LINE_ARGS) {
5347 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5348 * C equivalent value. Other combinations left unchanged (eg: \1).
5349 */
5350 if (*line == '\\') {
5351 int skip = 0;
5352 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5353 *line = line[1];
5354 skip = 1;
5355 }
5356 else if (line[1] == 'r') {
5357 *line = '\r';
5358 skip = 1;
5359 }
5360 else if (line[1] == 'n') {
5361 *line = '\n';
5362 skip = 1;
5363 }
5364 else if (line[1] == 't') {
5365 *line = '\t';
5366 skip = 1;
5367 }
5368 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005369 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 unsigned char hex1, hex2;
5371 hex1 = toupper(line[2]) - '0';
5372 hex2 = toupper(line[3]) - '0';
5373 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5374 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5375 *line = (hex1<<4) + hex2;
5376 skip = 3;
5377 }
5378 else {
5379 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005380 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 }
5382 }
5383 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005384 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385 end -= skip;
5386 }
5387 line++;
5388 }
5389 else if (*line == '#' || *line == '\n' || *line == '\r') {
5390 /* end of string, end of loop */
5391 *line = 0;
5392 break;
5393 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005394 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005395 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005396 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005397 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 line++;
5399 args[++arg] = line;
5400 }
5401 else {
5402 line++;
5403 }
5404 }
5405
5406 /* empty line */
5407 if (!**args)
5408 continue;
5409
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005410 if (*line) {
5411 /* we had to stop due to too many args.
5412 * Let's terminate the string, print the offending part then cut the
5413 * last arg.
5414 */
5415 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5416 line++;
5417 *line = '\0';
5418
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005419 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005420 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 args[arg] = line;
5423 }
5424
Willy Tarreau540abe42007-05-02 20:50:16 +02005425 /* zero out remaining args and ensure that at least one entry
5426 * is zeroed out.
5427 */
5428 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005429 args[arg] = line;
5430 }
5431
Willy Tarreau3842f002009-06-14 11:39:52 +02005432 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005433 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005434 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005435 for (arg=0; *args[arg+1]; arg++)
5436 args[arg] = args[arg+1]; // shift args after inversion
5437 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005438 else if (!strcmp(args[0], "default")) {
5439 kwm = KWM_DEF;
5440 for (arg=0; *args[arg+1]; arg++)
5441 args[arg] = args[arg+1]; // shift args after inversion
5442 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005443
Willy Tarreau3842f002009-06-14 11:39:52 +02005444 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5445 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005446 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005447 }
5448
Willy Tarreau977b8e42006-12-29 14:19:17 +01005449 if (!strcmp(args[0], "listen") ||
5450 !strcmp(args[0], "frontend") ||
5451 !strcmp(args[0], "backend") ||
5452 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005453 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005455 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005456 cursection = strdup(args[0]);
5457 }
5458 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005460 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005461 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005462 }
5463 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005464 confsect = CFG_USERLIST;
5465 free(cursection);
5466 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005467 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005468 else if (!strcmp(args[0], "peers")) {
5469 confsect = CFG_PEERS;
5470 free(cursection);
5471 cursection = strdup(args[0]);
5472 }
5473
Willy Tarreaubaaee002006-06-26 02:48:02 +02005474 /* else it's a section keyword */
5475
5476 switch (confsect) {
5477 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 break;
5480 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005481 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005483 case CFG_USERLIST:
5484 err_code |= cfg_parse_users(file, linenum, args, kwm);
5485 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005486 case CFG_PEERS:
5487 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5488 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005490 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005491 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005493
5494 if (err_code & ERR_ABORT)
5495 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005497 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005498 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005500 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005501}
5502
Willy Tarreaubb925012009-07-23 13:36:36 +02005503/*
5504 * Returns the error code, 0 if OK, or any combination of :
5505 * - ERR_ABORT: must abort ASAP
5506 * - ERR_FATAL: we can continue parsing but not start the service
5507 * - ERR_WARN: a warning has been emitted
5508 * - ERR_ALERT: an alert has been emitted
5509 * Only the two first ones can stop processing, the two others are just
5510 * indicators.
5511 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005512int check_config_validity()
5513{
5514 int cfgerr = 0;
5515 struct proxy *curproxy = NULL;
5516 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005517 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005518 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005519 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520
5521 /*
5522 * Now, check for the integrity of all that we have collected.
5523 */
5524
5525 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005526 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005528 /* first, we will invert the proxy list order */
5529 curproxy = NULL;
5530 while (proxy) {
5531 struct proxy *next;
5532
5533 next = proxy->next;
5534 proxy->next = curproxy;
5535 curproxy = proxy;
5536 if (!next)
5537 break;
5538 proxy = next;
5539 }
5540
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005542 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
5546
5547 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005548 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005549 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005550 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005551 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005552 unsigned int next_id;
5553
5554 if (!curproxy->uuid) {
5555 /* proxy ID not set, use automatic numbering with first
5556 * spare entry starting with next_pxid.
5557 */
5558 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5559 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5560 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005561 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005562 next_pxid++;
5563
Willy Tarreau55ea7572007-06-17 19:56:27 +02005564
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005566 /* ensure we don't keep listeners uselessly bound */
5567 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 curproxy = curproxy->next;
5569 continue;
5570 }
5571
Willy Tarreauff01a212009-03-15 13:46:16 +01005572 switch (curproxy->mode) {
5573 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005574 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005575 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005576 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5577 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005578 cfgerr++;
5579 }
5580
5581 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005582 Warning("config : servers will be ignored for %s '%s'.\n",
5583 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005584 break;
5585
5586 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005587 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005588 break;
5589
5590 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005591 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005592 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005593 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5594 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005595 cfgerr++;
5596 }
5597 break;
5598 }
5599
5600 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005601 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5602 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 cfgerr++;
5604 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005605
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005606 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005607 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005608 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005609 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5610 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005611 cfgerr++;
5612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005614 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005615 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5616 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005617 cfgerr++;
5618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005620 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005621 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5622 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005623 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005624 }
5625 }
5626 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5627 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5628 /* If no LB algo is set in a backend, and we're not in
5629 * transparent mode, dispatch mode nor proxy mode, we
5630 * want to use balance roundrobin by default.
5631 */
5632 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5633 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
5635 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005636
Willy Tarreau82936582007-11-30 15:20:09 +01005637 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5638 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005639 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5640 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005641 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005642 }
5643
Willy Tarreauef781042010-01-27 11:53:01 +01005644 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5645 curproxy->options &= ~PR_O2_CHK_SNDST;
5646 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5647 "send-state", proxy_type_str(curproxy), curproxy->id);
5648 err_code |= ERR_WARN;
5649 }
5650
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005651 /* if a default backend was specified, let's find it */
5652 if (curproxy->defbe.name) {
5653 struct proxy *target;
5654
Alex Williams96532db2009-11-01 21:27:13 -05005655 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005656 if (!target) {
5657 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5658 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005659 cfgerr++;
5660 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005661 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5662 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005663 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005664 } else {
5665 free(curproxy->defbe.name);
5666 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005667 /* we force the backend to be present on at least all of
5668 * the frontend's processes.
5669 */
5670 target->bind_proc = curproxy->bind_proc ?
5671 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 }
5673 }
5674
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005675 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005676 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5677 /* map jump target for ACT_SETBE in req_rep chain */
5678 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005679 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005680 struct proxy *target;
5681
Willy Tarreaua496b602006-12-17 23:15:24 +01005682 if (exp->action != ACT_SETBE)
5683 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005684
Alex Williams96532db2009-11-01 21:27:13 -05005685 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005686 if (!target) {
5687 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5688 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005689 cfgerr++;
5690 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005691 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5692 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005693 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005694 } else {
5695 free((void *)exp->replace);
5696 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005697 /* we force the backend to be present on at least all of
5698 * the frontend's processes.
5699 */
5700 target->bind_proc = curproxy->bind_proc ?
5701 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005702 }
5703 }
5704 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005705
5706 /* find the target proxy for 'use_backend' rules */
5707 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005708 struct proxy *target;
5709
Alex Williams96532db2009-11-01 21:27:13 -05005710 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005711
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005712 if (!target) {
5713 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5714 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005715 cfgerr++;
5716 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005717 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5718 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005719 cfgerr++;
5720 } else {
5721 free((void *)rule->be.name);
5722 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005723 /* we force the backend to be present on at least all of
5724 * the frontend's processes.
5725 */
5726 target->bind_proc = curproxy->bind_proc ?
5727 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005728 }
5729 }
5730
Emeric Brunb982a3d2010-01-04 15:45:53 +01005731 /* find the target table for 'stick' rules */
5732 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5733 struct proxy *target;
5734
Emeric Brun1d33b292010-01-04 15:47:17 +01005735 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5736 if (mrule->flags & STK_IS_STORE)
5737 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5738
Emeric Brunb982a3d2010-01-04 15:45:53 +01005739 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005740 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005741 else
5742 target = curproxy;
5743
5744 if (!target) {
5745 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5746 curproxy->id, mrule->table.name);
5747 cfgerr++;
5748 }
5749 else if (target->table.size == 0) {
5750 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5751 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5752 cfgerr++;
5753 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005754 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005755 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5756 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5757 cfgerr++;
5758 }
5759 else {
5760 free((void *)mrule->table.name);
5761 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005762 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005763 }
5764 }
5765
5766 /* find the target table for 'store response' rules */
5767 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5768 struct proxy *target;
5769
Emeric Brun1d33b292010-01-04 15:47:17 +01005770 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5771
Emeric Brunb982a3d2010-01-04 15:45:53 +01005772 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005773 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005774 else
5775 target = curproxy;
5776
5777 if (!target) {
5778 Alert("Proxy '%s': unable to find store table '%s'.\n",
5779 curproxy->id, mrule->table.name);
5780 cfgerr++;
5781 }
5782 else if (target->table.size == 0) {
5783 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5784 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5785 cfgerr++;
5786 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005787 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005788 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5789 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5790 cfgerr++;
5791 }
5792 else {
5793 free((void *)mrule->table.name);
5794 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005795 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005796 }
5797 }
5798
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005799 /* find the target table for 'tcp-request' layer 4 rules */
5800 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5801 struct proxy *target;
5802
Willy Tarreau56123282010-08-06 19:06:56 +02005803 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005804 continue;
5805
5806 if (trule->act_prm.trk_ctr.table.n)
5807 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5808 else
5809 target = curproxy;
5810
5811 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005812 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5813 curproxy->id, trule->act_prm.trk_ctr.table.n,
5814 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005815 cfgerr++;
5816 }
5817 else if (target->table.size == 0) {
5818 Alert("Proxy '%s': table '%s' used but not configured.\n",
5819 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5820 cfgerr++;
5821 }
5822 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005823 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 +02005824 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5825 cfgerr++;
5826 }
5827 else {
5828 free(trule->act_prm.trk_ctr.table.n);
5829 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005830 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005831 * to pass a list of counters to track and allocate them right here using
5832 * stktable_alloc_data_type().
5833 */
5834 }
5835 }
5836
Willy Tarreaud1f96522010-08-03 19:34:32 +02005837 /* find the target table for 'tcp-request' layer 6 rules */
5838 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5839 struct proxy *target;
5840
Willy Tarreau56123282010-08-06 19:06:56 +02005841 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005842 continue;
5843
5844 if (trule->act_prm.trk_ctr.table.n)
5845 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5846 else
5847 target = curproxy;
5848
5849 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005850 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5851 curproxy->id, trule->act_prm.trk_ctr.table.n,
5852 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005853 cfgerr++;
5854 }
5855 else if (target->table.size == 0) {
5856 Alert("Proxy '%s': table '%s' used but not configured.\n",
5857 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5858 cfgerr++;
5859 }
5860 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005861 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 +02005862 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5863 cfgerr++;
5864 }
5865 else {
5866 free(trule->act_prm.trk_ctr.table.n);
5867 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005868 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005869 * to pass a list of counters to track and allocate them right here using
5870 * stktable_alloc_data_type().
5871 */
5872 }
5873 }
5874
Emeric Brun32da3c42010-09-23 18:39:19 +02005875 if (curproxy->table.peers.name) {
5876 struct peers *curpeers = peers;
5877
5878 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5879 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5880 free((void *)curproxy->table.peers.name);
5881 curproxy->table.peers.p = peers;
5882 break;
5883 }
5884 }
5885
5886 if (!curpeers) {
5887 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5888 curproxy->id, curproxy->table.peers.name);
5889 cfgerr++;
5890 }
5891 else if (!curpeers->peers_fe) {
5892 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5893 curproxy->id, curpeers->id);
5894 cfgerr++;
5895 }
5896 }
5897
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005898 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5899 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005900 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5901 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5902 "proxy", curproxy->id);
5903 cfgerr++;
5904 goto out_uri_auth_compat;
5905 }
5906
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005907 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005908 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005909 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005910 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005911
Willy Tarreau95fa4692010-02-01 13:05:50 +01005912 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5913 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005914
5915 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005916 uri_auth_compat_req[i++] = "realm";
5917 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5918 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005919
Willy Tarreau95fa4692010-02-01 13:05:50 +01005920 uri_auth_compat_req[i++] = "unless";
5921 uri_auth_compat_req[i++] = "{";
5922 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5923 uri_auth_compat_req[i++] = "}";
5924 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005925
Willy Tarreau95fa4692010-02-01 13:05:50 +01005926 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5927 if (!req_acl) {
5928 cfgerr++;
5929 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005930 }
5931
Willy Tarreau95fa4692010-02-01 13:05:50 +01005932 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5933
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005934 if (curproxy->uri_auth->auth_realm) {
5935 free(curproxy->uri_auth->auth_realm);
5936 curproxy->uri_auth->auth_realm = NULL;
5937 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005938
5939 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005940 }
5941out_uri_auth_compat:
5942
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005943 cfgerr += acl_find_targets(curproxy);
5944
Willy Tarreau2738a142006-07-08 17:28:09 +02005945 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005946 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005947 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005948 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005949 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005950 " | While not properly invalid, you will certainly encounter various problems\n"
5951 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005952 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005953 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005954 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005955 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005956
Willy Tarreau1fa31262007-12-03 00:36:16 +01005957 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5958 * We must still support older configurations, so let's find out whether those
5959 * parameters have been set or must be copied from contimeouts.
5960 */
5961 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005962 if (!curproxy->timeout.tarpit ||
5963 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005964 /* tarpit timeout not set. We search in the following order:
5965 * default.tarpit, curr.connect, default.connect.
5966 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005967 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005968 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005969 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005970 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005971 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005972 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005973 }
5974 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005975 (!curproxy->timeout.queue ||
5976 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005977 /* queue timeout not set. We search in the following order:
5978 * default.queue, curr.connect, default.connect.
5979 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005980 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005981 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005982 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005983 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005984 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005985 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005986 }
5987 }
5988
Willy Tarreau07a54902010-03-29 18:33:29 +02005989 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005990 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5991 curproxy->check_req = (char *)malloc(curproxy->check_len);
5992 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005993 }
5994
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005995 /* The small pools required for the capture lists */
5996 if (curproxy->nb_req_cap)
5997 curproxy->req_cap_pool = create_pool("ptrcap",
5998 curproxy->nb_req_cap * sizeof(char *),
5999 MEM_F_SHARED);
6000 if (curproxy->nb_rsp_cap)
6001 curproxy->rsp_cap_pool = create_pool("ptrcap",
6002 curproxy->nb_rsp_cap * sizeof(char *),
6003 MEM_F_SHARED);
6004
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006005 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6006 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6007 MEM_F_SHARED);
6008
Willy Tarreau86034312006-12-29 00:10:33 +01006009 /* for backwards compatibility with "listen" instances, if
6010 * fullconn is not set but maxconn is set, then maxconn
6011 * is used.
6012 */
6013 if (!curproxy->fullconn)
6014 curproxy->fullconn = curproxy->maxconn;
6015
Willy Tarreaubaaee002006-06-26 02:48:02 +02006016 /* first, we will invert the servers list order */
6017 newsrv = NULL;
6018 while (curproxy->srv) {
6019 struct server *next;
6020
6021 next = curproxy->srv->next;
6022 curproxy->srv->next = newsrv;
6023 newsrv = curproxy->srv;
6024 if (!next)
6025 break;
6026 curproxy->srv = next;
6027 }
6028
Willy Tarreaudd701652010-05-25 23:03:02 +02006029 /* assign automatic UIDs to servers which don't have one yet */
6030 next_id = 1;
6031 newsrv = curproxy->srv;
6032 while (newsrv != NULL) {
6033 if (!newsrv->puid) {
6034 /* server ID not set, use automatic numbering with first
6035 * spare entry starting with next_svid.
6036 */
6037 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6038 newsrv->conf.id.key = newsrv->puid = next_id;
6039 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6040 }
6041 next_id++;
6042 newsrv = newsrv->next;
6043 }
6044
Willy Tarreau20697042007-11-15 23:26:18 +01006045 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006046 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006047
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006048 /* We have to initialize the server lookup mechanism depending
6049 * on what LB algorithm was choosen.
6050 */
6051
6052 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6053 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6054 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006055 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6056 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6057 init_server_map(curproxy);
6058 } else {
6059 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6060 fwrr_init_server_groups(curproxy);
6061 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006062 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006063
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006064 case BE_LB_KIND_LC:
6065 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006066 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006067 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006068
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006069 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006070 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6071 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6072 chash_init_server_tree(curproxy);
6073 } else {
6074 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6075 init_server_map(curproxy);
6076 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006077 break;
6078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006079
6080 if (curproxy->options & PR_O_LOGASAP)
6081 curproxy->to_log &= ~LW_BYTES;
6082
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006083 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6084 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6085 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6086 proxy_type_str(curproxy), curproxy->id);
6087 err_code |= ERR_WARN;
6088 }
6089
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006090 if (curproxy->mode != PR_MODE_HTTP) {
6091 int optnum;
6092
6093 if (curproxy->options & PR_O_COOK_ANY) {
6094 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6095 proxy_type_str(curproxy), curproxy->id);
6096 err_code |= ERR_WARN;
6097 }
6098
6099 if (curproxy->uri_auth) {
6100 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6101 proxy_type_str(curproxy), curproxy->id);
6102 err_code |= ERR_WARN;
6103 curproxy->uri_auth = NULL;
6104 }
6105
6106 if (curproxy->options & PR_O_FWDFOR) {
6107 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6108 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6109 err_code |= ERR_WARN;
6110 curproxy->options &= ~PR_O_FWDFOR;
6111 }
6112
6113 if (curproxy->options & PR_O_ORGTO) {
6114 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6115 "originalto", proxy_type_str(curproxy), curproxy->id);
6116 err_code |= ERR_WARN;
6117 curproxy->options &= ~PR_O_ORGTO;
6118 }
6119
6120 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6121 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6122 (curproxy->cap & cfg_opts[optnum].cap) &&
6123 (curproxy->options & cfg_opts[optnum].val)) {
6124 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6125 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6126 err_code |= ERR_WARN;
6127 curproxy->options &= ~cfg_opts[optnum].val;
6128 }
6129 }
6130
6131 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6132 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6133 (curproxy->cap & cfg_opts2[optnum].cap) &&
6134 (curproxy->options2 & cfg_opts2[optnum].val)) {
6135 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6136 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6137 err_code |= ERR_WARN;
6138 curproxy->options2 &= ~cfg_opts2[optnum].val;
6139 }
6140 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006141
Willy Tarreauefa5f512010-03-30 20:13:29 +02006142#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006143 if (curproxy->bind_hdr_occ) {
6144 curproxy->bind_hdr_occ = 0;
6145 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6146 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6147 err_code |= ERR_WARN;
6148 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006149#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006150 }
6151
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006153 * ensure that we're not cross-dressing a TCP server into HTTP.
6154 */
6155 newsrv = curproxy->srv;
6156 while (newsrv != NULL) {
6157 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006158 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6159 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006160 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006161 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006162
Willy Tarreauefa5f512010-03-30 20:13:29 +02006163#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006164 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6165 newsrv->bind_hdr_occ = 0;
6166 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6167 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6168 err_code |= ERR_WARN;
6169 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006170#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006171 newsrv = newsrv->next;
6172 }
6173
6174 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 * If this server supports a maxconn parameter, it needs a dedicated
6176 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006177 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 */
6179 newsrv = curproxy->srv;
6180 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006181 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 /* Only 'minconn' was specified, or it was higher than or equal
6183 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6184 * this will avoid further useless expensive computations.
6185 */
6186 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006187 } else if (newsrv->maxconn && !newsrv->minconn) {
6188 /* minconn was not specified, so we set it to maxconn */
6189 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006190 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006191 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6192 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006193 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006194 }
6195
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006196 if (newsrv->trackit) {
6197 struct proxy *px;
6198 struct server *srv;
6199 char *pname, *sname;
6200
6201 pname = newsrv->trackit;
6202 sname = strrchr(pname, '/');
6203
6204 if (sname)
6205 *sname++ = '\0';
6206 else {
6207 sname = pname;
6208 pname = NULL;
6209 }
6210
6211 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006212 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006213 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006214 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6215 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006216 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006217 cfgerr++;
6218 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006219 }
6220 } else
6221 px = curproxy;
6222
6223 srv = findserver(px, sname);
6224 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006225 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6226 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006227 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006228 cfgerr++;
6229 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006230 }
6231
6232 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006233 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006234 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006235 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006236 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006237 cfgerr++;
6238 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006239 }
6240
6241 if (curproxy != px &&
6242 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006243 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006244 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006245 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006246 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006247 cfgerr++;
6248 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006249 }
6250
6251 newsrv->tracked = srv;
6252 newsrv->tracknext = srv->tracknext;
6253 srv->tracknext = newsrv;
6254
6255 free(newsrv->trackit);
6256 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006257 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006258 newsrv = newsrv->next;
6259 }
6260
Willy Tarreauc1a21672009-08-16 22:37:44 +02006261 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006262 curproxy->accept = frontend_accept;
6263
Willy Tarreauc1a21672009-08-16 22:37:44 +02006264 if (curproxy->tcp_req.inspect_delay ||
6265 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006266 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006267
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006268 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006269 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006270 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006271 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006272
6273 /* both TCP and HTTP must check switching rules */
6274 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6275 }
6276
6277 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006278 if (curproxy->tcp_req.inspect_delay ||
6279 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6280 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6281
Emeric Brun97679e72010-09-23 17:56:44 +02006282 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6283 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6284
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006285 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006286 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006287 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006288 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006289
6290 /* If the backend does requires RDP cookie persistence, we have to
6291 * enable the corresponding analyser.
6292 */
6293 if (curproxy->options2 & PR_O2_RDPC_PRST)
6294 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6295 }
6296
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006297 listener = NULL;
6298 while (curproxy->listen) {
6299 struct listener *next;
6300
6301 next = curproxy->listen->next;
6302 curproxy->listen->next = listener;
6303 listener = curproxy->listen;
6304
6305 if (!next)
6306 break;
6307
6308 curproxy->listen = next;
6309 }
6310
Willy Tarreaue6b98942007-10-29 01:09:36 +01006311 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006312 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006313 listener = curproxy->listen;
6314 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006315 if (!listener->luid) {
6316 /* listener ID not set, use automatic numbering with first
6317 * spare entry starting with next_luid.
6318 */
6319 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6320 listener->conf.id.key = listener->luid = next_id;
6321 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006322 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006323 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006324
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006325 /* enable separate counters */
6326 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6327 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6328 if (!listener->name) {
6329 sprintf(trash, "sock-%d", listener->luid);
6330 listener->name = strdup(trash);
6331 }
6332 }
6333
Willy Tarreaue6b98942007-10-29 01:09:36 +01006334 if (curproxy->options & PR_O_TCP_NOLING)
6335 listener->options |= LI_O_NOLINGER;
6336 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006337 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006338 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006339 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006340 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006341 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006342 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006343
Willy Tarreau8a956912010-10-15 14:27:08 +02006344 if (listener->options & LI_O_ACC_PROXY)
6345 listener->analysers |= AN_REQ_DECODE_PROXY;
6346
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006347 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6348 listener->options |= LI_O_TCP_RULES;
6349
Willy Tarreaude3041d2010-05-31 10:56:17 +02006350 if (curproxy->mon_mask.s_addr)
6351 listener->options |= LI_O_CHK_MONNET;
6352
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006353 /* smart accept mode is automatic in HTTP mode */
6354 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6355 (curproxy->mode == PR_MODE_HTTP &&
6356 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6357 listener->options |= LI_O_NOQUICKACK;
6358
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006359 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006360 listener = listener->next;
6361 }
6362
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006363 /* Check multi-process mode compatibility for the current proxy */
6364 if (global.nbproc > 1) {
6365 int nbproc = 0;
6366 if (curproxy->bind_proc) {
6367 int proc;
6368 for (proc = 0; proc < global.nbproc; proc++) {
6369 if (curproxy->bind_proc & (1 << proc)) {
6370 nbproc++;
6371 }
6372 }
6373 } else {
6374 nbproc = global.nbproc;
6375 }
6376 if (curproxy->table.peers.name) {
6377 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6378 curproxy->id);
6379 cfgerr++;
6380 }
6381 if (nbproc > 1) {
6382 if (curproxy->uri_auth) {
6383 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6384 curproxy->id);
6385 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6386 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6387 curproxy->id);
6388 }
6389 }
6390 if (curproxy->appsession_name) {
6391 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6392 curproxy->id);
6393 }
6394 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6395 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6396 curproxy->id);
6397 }
6398 }
6399 }
6400
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 curproxy = curproxy->next;
6402 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006403
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006404 /* Check multi-process mode compatibility */
6405 if (global.nbproc > 1) {
6406 if (global.stats_fe) {
6407 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6408 }
6409 }
6410
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006411 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6412 struct auth_users *curuser;
6413 int g;
6414
6415 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6416 unsigned int group_mask = 0;
6417 char *group = NULL;
6418
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006419 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006420 continue;
6421
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006422 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006423
6424 for (g = 0; g < curuserlist->grpcnt; g++)
6425 if (!strcmp(curuserlist->groups[g], group))
6426 break;
6427
6428 if (g == curuserlist->grpcnt) {
6429 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6430 curuserlist->name, group, curuser->user);
6431 err_code |= ERR_ALERT | ERR_FATAL;
6432 goto out;
6433 }
6434
6435 group_mask |= (1 << g);
6436 }
6437
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006438 free(curuser->u.groups);
6439 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006440 }
6441
6442 for (g = 0; g < curuserlist->grpcnt; g++) {
6443 char *user = NULL;
6444
6445 if (!curuserlist->groupusers[g])
6446 continue;
6447
6448 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6449 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6450 if (!strcmp(curuser->user, user))
6451 break;
6452
6453 if (!curuser) {
6454 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6455 curuserlist->name, user, curuserlist->groups[g]);
6456 err_code |= ERR_ALERT | ERR_FATAL;
6457 goto out;
6458 }
6459
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006460 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006461 }
6462
6463 free(curuserlist->groupusers[g]);
6464 }
6465
6466 free(curuserlist->groupusers);
6467
6468#ifdef DEBUG_AUTH
6469 for (g = 0; g < curuserlist->grpcnt; g++) {
6470 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6471
6472 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6473 if (curuser->group_mask & (1 << g))
6474 fprintf(stderr, " %s", curuser->user);
6475 }
6476
6477 fprintf(stderr, "\n");
6478 }
6479#endif
6480
6481 }
6482
Willy Tarreau056f5682010-06-06 15:51:11 +02006483 /* initialize stick-tables on backend capable proxies. This must not
6484 * be done earlier because the data size may be discovered while parsing
6485 * other proxies.
6486 */
6487 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006488 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006489
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006490 /*
6491 * Recount currently required checks.
6492 */
6493
6494 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6495 int optnum;
6496
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006497 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6498 if (curproxy->options & cfg_opts[optnum].val)
6499 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006500
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006501 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6502 if (curproxy->options2 & cfg_opts2[optnum].val)
6503 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006504 }
6505
Willy Tarreaubb925012009-07-23 13:36:36 +02006506 if (cfgerr > 0)
6507 err_code |= ERR_ALERT | ERR_FATAL;
6508 out:
6509 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006510}
6511
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006512/*
6513 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6514 * parsing sessions.
6515 */
6516void cfg_register_keywords(struct cfg_kw_list *kwl)
6517{
6518 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6519}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006521/*
6522 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6523 */
6524void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6525{
6526 LIST_DEL(&kwl->list);
6527 LIST_INIT(&kwl->list);
6528}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529
6530/*
6531 * Local variables:
6532 * c-indent-level: 8
6533 * c-basic-offset: 8
6534 * End:
6535 */